@ECHO OFF
REM Copyright (c) DataStax, Inc.
REM
REM Licensed under the Apache License, Version 2.0 (the "License");
REM you may not use this file except in compliance with the License.
REM You may obtain a copy of the License at
REM
REM http://www.apache.org/licenses/LICENSE-2.0
REM
REM Unless required by applicable law or agreed to in writing, software
REM distributed under the License is distributed on an "AS IS" BASIS,
REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
REM See the License for the specific language governing permissions and
REM limitations under the License.

REM Enable delayed expansion (multiple var assignments) and local variables
SETLOCAL ENABLEDELAYEDEXPANSION

SET BATCH_DIRECTORY=%~D0%~P0
SET ABSOLUTE_BATCH_DIRECTORY=%~DP0
SET BATCH_FILENAME=%~N0%~X0

REM Exit code constants
SET EXIT_CODE_INVALID_SYSTEM_ARCHITECTURE=1
SET EXIT_CODE_MISSING_VISUAL_STUDIO=2
SET EXIT_CODE_MISSING_BUILD_DEPENDENCY=3
SET EXIT_CODE_INVALID_BUILD_DEPENDENCY_VERSION=4
SET EXIT_CODE_CLONE_FAILED=5
SET EXIT_CODE_BUILD_DEPENDENCY_FAILED=6
SET EXIT_CODE_BUILD_DRIVER_FAILED=7
SET EXIT_CODE_INVALID_VERSION=8
SET EXIT_CODE_PACKAGE_FAILED=9

REM Argument constants
SET ARGUMENT_BUILD_TYPE_DEBUG=--DEBUG
SET ARGUMENT_BUILD_TYPE_RELEASE=--RELEASE
SET ARGUMENT_BUILD_DEPENDENCIES_ONLY=--DEPENDENCIES-ONLY
SET ARGUMENT_DISABLE_CLEAN_BUILD=--DISABLE-CLEAN
SET ARGUMENT_DISABLE_OPENSSL=--DISABLE-OPENSSL
SET ARGUMENT_ENABLE_EXAMPLES=--ENABLE-EXAMPLES
SET ARGUMENT_ENABLE_BUILD_PACKAGES=--ENABLE-PACKAGES
SET ARGUMENT_ENABLE_TESTS=--ENABLE-TESTS
SET ARGUMENT_ENABLE_INTEGRATION_TESTS=--ENABLE-INTEGRATION-TESTS
SET ARGUMENT_ENABLE_UNIT_TESTS=--ENABLE-UNIT-TESTS
SET ARGUMENT_ENABLE_LIBSSH2=--ENABLE-LIBSSH2
SET ARGUMENT_ENABLE_ZLIB=--ENABLE-ZLIB
SET ARGUMENT_GENERATE_SOLUTION=--GENERATE-SOLUTION
SET ARGUMENT_INSTALLATION_DIRECTORY=--INSTALL-DIR
SET ARGUMENT_OPENSSL_VERSION=--OPENSSL-VERSION
SET ARGUMENT_USE_BOOST_ATOMIC=--USE-BOOST-ATOMIC
SET ARGUMENT_LIBRARY_TYPE_SHARED=--SHARED
SET ARGUMENT_LIBRARY_TYPE_STATIC=--STATIC
SET ARGUMENT_ENABLE_SHARED_OPENSSL=--ENABLE-SHARED-OPENSSL
SET ARGUMENT_TARGET_ARCHITECTURE_32BIT=--X86
SET ARGUMENT_TARGET_ARCHITECTURE_64BIT=--X64
SET ARGUMENT_TARGET_COMPILER=--TARGET-COMPILER
SET ARGUMENT_HELP=--HELP

REM Option/Value constants
SET ARCHITECTURE_32BIT=32
SET ARCHITECTURE_64BIT=64
SET BUILD_TYPE_DEBUG=DEBUG
SET BUILD_TYPE_RELEASE=RELEASE
SET LIBRARY_TYPE_SHARED=SHARED
SET LIBRARY_TYPE_STATIC=STATIC
SET TRUE=1
SET FALSE=0
SET YES=1
SET NO=2

REM Determine the system architecture (32/64 bit)
SET ARCHITECTURE_REGISTRY_LOCATION_QUERY=HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0
SET ARCHITECTURE_REGISTRY_LOCATION_KEY=Identifier
REG QUERY %ARCHITECTURE_REGISTRY_LOCATION_QUERY% /V %ARCHITECTURE_REGISTRY_LOCATION_KEY% | FIND /I "x86" > NUL && SET SYSTEM_ARCHITECTURE=%ARCHITECTURE_32BIT% || SET SYSTEM_ARCHITECTURE=%ARCHITECTURE_64BIT%

REM Dependency executable constants
SET CMAKE=cmake.exe
REM Add CMake options here (e.g. --debug-output, --trace, --trace-expand)
SET "CMAKE_OPTIONS="
SET "DOWNLOAD_URL_CMAKE=http://www.cmake.org/download"
SET GIT=git.exe
SET "DOWNLOAD_URL_GIT=http://git-scm.com/downloads"
SET PERL=perl.exe
SET "DOWNLOAD_URL_PERL=https://www.perl.org/get.html#win32"
SET PYTHON=python.exe
SET "DOWNLOAD_URL_PYTHON=https://www.python.org/downloads/"
SET DEVENV=devenv.exe
SET MSBUILD=msbuild.exe
SET NMAKE=nmake.exe
SET "DOWNLOAD_URL_VISUAL_STUDIO=https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15"
SET ZIP=7z.exe
SET "DOWNLOAD_URL_ZIP=http://www.7-zip.org/download.html"
SET "VSWHERE=!ABSOLUTE_BATCH_DIRECTORY!\bin\vswhere.exe"

REM Minimum version build dependency constants
SET MINIMUM_VERSION_REQUIRED_CMAKE=3.4.0
SET MINIMUM_VERSION_REQUIRED_PYTHON=2.7.0

REM Build constants
SET BUILD_DIRECTORY=build
SET "ABSOLUTE_BUILD_DIRECTORY=%BATCH_DIRECTORY%\%BUILD_DIRECTORY%"
SET BUILD_PACKAGE_PREFIX=cassandra-cpp-driver
SET DRIVER_DRIVER_DIRECTORY=driver
SET PACKAGES_DIRECTORY=packages
SET "ABSOLUTE_PACKAGES_DIRECTORY=%ABSOLUTE_BUILD_DIRECTORY%\%PACKAGES_DIRECTORY%"

REM Build dependency constants
SET DEPENDENCIES_DIRECTORY=dependencies
SET "ABSOLUTE_DEPENDENCIES_DIRECTORY=%ABSOLUTE_BUILD_DIRECTORY%\%DEPENDENCIES_DIRECTORY%"
SET DEPENDENCIES_SOURCE_DIRECTORY=src
SET DEPENDENCIES_LIBRARIES_DIRECTORY=libs
SET BOOST_REPOSITORY_URL=https://github.com/boostorg/
SET BOOST_DIRECTORY=boost
SET BOOST_BRANCH_TAG_VERSION=boost-1.66.0
SET LIBUV_REPOSITORY_URL=https://github.com/libuv/libuv.git
SET LIBUV_DIRECTORY=libuv
SET LIBUV_BRANCH_TAG_VERSION=v1.20.0
SET LIBUV_PACKAGE_VERSION=1.20.0
SET GYP_REPOSITORY_URL=https://chromium.googlesource.com/external/gyp.git
SET LIBSSH2_REPOSITORY_URL=https://github.com/libssh2/libssh2.git
SET LIBSSH2_DIRECTORY=libssh2
SET LIBSSH2_BRANCH_TAG_VERSION=libssh2-1.8.0
SET LIBSSH2_PACKAGE_VERSION=1.8.0
SET OPENSSL_REPOSITORY_URL=https://github.com/openssl/openssl.git
SET OPENSSL_DIRECTORY=openssl
SET OPENSSL_1_0_BRANCH_TAG_VERSION=OpenSSL_1_0_2o
SET OPENSSL_1_1_BRANCH_TAG_VERSION=OpenSSL_1_1_0h
SET OPENSSL_PACKAGE_VERSION=1.0.2o
SET "SUPPORTED_OPENSSL_VERSIONS=1_0 1_1"
SET "SUPPORTED_OPENSSL_DISPLAY_VERSIONS=1.0 1.1"
SET ZLIB_REPOSITORY_URL=https://github.com/madler/zlib.git
SET ZLIB_DIRECTORY=zlib
SET ZLIB_BRANCH_TAG_VERSION=v1.2.11

REM Library directory constants
SET LIBRARY_INCLUDE_DIRECTORY=include
SET LIBRARY_BINARY_DIRECTORY=lib
SET LIBRARY_RUNTIME_DIRECTORY=bin
SET "ABSOLUTE_DRIVER_LIBRARY_DIRECTORY=%ABSOLUTE_BUILD_DIRECTORY%\%LIBRARY_BINARY_DIRECTORY%"
SET "ABSOLUTE_DEPENDENCIES_LIBRARIES_DIRECTORY=%ABSOLUTE_DEPENDENCIES_DIRECTORY%\%DEPENDENCIES_LIBRARIES_DIRECTORY%"
SET "ABSOLUTE_LIBUV_LIBRARY_DIRECTORY=%ABSOLUTE_DEPENDENCIES_LIBRARIES_DIRECTORY%\%LIBUV_DIRECTORY%"
SET "ABSOLUTE_LIBSSH2_LIBRARY_DIRECTORY=%ABSOLUTE_DEPENDENCIES_LIBRARIES_DIRECTORY%\%LIBSSH2_DIRECTORY%"
SET "ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY=%ABSOLUTE_DEPENDENCIES_LIBRARIES_DIRECTORY%\%OPENSSL_DIRECTORY%"
SET "ABSOLUTE_ZLIB_LIBRARY_DIRECTORY=%ABSOLUTE_DEPENDENCIES_LIBRARIES_DIRECTORY%\%ZLIB_DIRECTORY%"

REM Log filename constants
SET LOG_DIRECTORY=log
SET "ABSOLUTE_LOG_DIRECTORY=%ABSOLUTE_BUILD_DIRECTORY%\%LOG_DIRECTORY%"
SET "LOG_BOOST_CLONE=%ABSOLUTE_LOG_DIRECTORY%\boost.log"
SET "LOG_DRIVER_BUILD=%ABSOLUTE_LOG_DIRECTORY%\driver.log"
SET "LOG_LIBUV_BUILD=%ABSOLUTE_LOG_DIRECTORY%\libuv.log"
SET "LOG_LIBSSH2_BUILD=%ABSOLUTE_LOG_DIRECTORY%\libssh2.log"
SET "LOG_OPENSSL_BUILD=%ABSOLUTE_LOG_DIRECTORY%\openssl.log"
SET "LOG_PACKAGE_BUILD=%ABSOLUTE_LOG_DIRECTORY%\package.log"
SET "LOG_ZLIB_BUILD=%ABSOLUTE_LOG_DIRECTORY%\zlib.log"

REM Build defaults (can be updated via command line)
SET BUILD_TYPE=%BUILD_TYPE_RELEASE%
SET BUILD_DEPENDENCIES_ONLY=%FALSE%
SET ENABLE_BUILD_PACKAGES=%FALSE%
SET ENABLE_CLEAN_BUILD=%TRUE%
SET ENABLE_EXAMPLES=%FALSE%
SET ENABLE_OPENSSL=%TRUE%
SET ENABLE_TESTS=%FALSE%
SET ENABLE_INTEGRATION_TESTS=%FALSE%
SET ENABLE_UNIT_TESTS=%FALSE%
SET ENABLE_LIBSSH2=%FALSE%
SET ENABLE_ZLIB=%FALSE%
SET GENERATE_SOLUTION=%FALSE%
SET LIBRARY_TYPE=%LIBRARY_TYPE_SHARED%
SET ENABLE_SHARED_OPENSSL=%FALSE%
SET OPENSSL_VERSION=1_0
SET TARGET_ARCHITECTURE=%SYSTEM_ARCHITECTURE%
SET USE_BOOST_ATOMIC=%FALSE%
SET ARGUMENT_IS_TEST=%FALSE%
SET IS_TESTING_ENABLED=%FALSE%

REM Parse command line arguments
:ARGUMENT_LOOP
IF NOT [%1] == [] (
  REM Get the current argument
  CALL :UPPERCASE %1 ARGUMENT
  SHIFT

  REM Build type (debug/release)
  IF "!ARGUMENT!" == "!ARGUMENT_BUILD_TYPE_DEBUG!" (
    SET BUILD_TYPE=!BUILD_TYPE_DEBUG!
  )
  IF "!ARGUMENT!" == "!ARGUMENT_BUILD_TYPE_RELEASE!" (
    SET BUILD_TYPE=!BUILD_TYPE_RELEASE!
  )

  REM Library type
  IF "!ARGUMENT!" == "!ARGUMENT_LIBRARY_TYPE_SHARED!" (
    SET LIBRARY_TYPE=!LIBRARY_TYPE_SHARED!
  )
  IF "!ARGUMENT!" == "!ARGUMENT_LIBRARY_TYPE_STATIC!" (
    SET LIBRARY_TYPE=!LIBRARY_TYPE_STATIC!
  )
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_SHARED_OPENSSL!" (
    SET ENABLE_SHARED_OPENSSL=!TRUE!
  )

  REM Target architecture (32/64 bit)
  IF "!ARGUMENT!" == "!ARGUMENT_TARGET_ARCHITECTURE_32BIT!" (
    SET TARGET_ARCHITECTURE=!ARCHITECTURE_32BIT!
  )
  IF "!ARGUMENT!" == "!ARGUMENT_TARGET_ARCHITECTURE_64BIT!" (
    REM Ensure the 64-bit build would be able to proceed
    IF NOT !SYSTEM_ARCHITECTURE! EQU !ARCHITECTURE_64BIT! (
      ECHO Invalid System Architecture: Unable to build 64-bit project on 32-bit OS
      EXIT /B !EXIT_CODE_INVALID_SYSTEM_ARCHITECTURE!
    )
    SET TARGET_ARCHITECTURE=!ARCHITECTURE_64BIT!
  )

  REM Target compiler (Visual Studio)
  IF "!ARGUMENT!" == "!ARGUMENT_TARGET_COMPILER!" (
    REM Make sure the compiler is valid
    IF [%2] == [] (
      ECHO Invalid Compiler: Visual Studio version must be supplied
      EXIT /B !EXIT_CODE_MISSING_VISUAL_STUDIO!
    ) ELSE (
      REM Get the compiler version to use
      CALL :UPPERCASE %2 TARGET_COMPILER_VERSION
      SHIFT

      REM Ensure the targeted compiler is valid
      IF NOT "!TARGET_COMPILER_VERSION!" == "100" (
        IF NOT "!TARGET_COMPILER_VERSION!" == "110" (
          IF NOT "!TARGET_COMPILER_VERSION!" == "120" (
            IF NOT "!TARGET_COMPILER_VERSION!" == "140" (
              IF NOT "!TARGET_COMPILER_VERSION!" == "141" (
                ECHO Invalid Compiler Version: 100, 110, 120, 140, or 141 must be supplied
                EXIT /B !EXIT_CODE_MISSING_VISUAL_STUDIO!
              )
            )
          )
        )
      )
    )
  )

  REM Enable build of examples
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_EXAMPLES!" (
    SET ENABLE_EXAMPLES=!TRUE!
  )

  REM Enable package build
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_BUILD_PACKAGES!" (
    SET ENABLE_BUILD_PACKAGES=!TRUE!

    REM Make sure the version information exists
    IF [%2] == [] (
      ECHO Invalid Version: Version must be supplied when enabling packages
      EXIT /B !EXIT_CODE_INVALID_VERSION!
    ) ELSE (
      REM Get the version information
      SET "BUILD_PACKAGE_VERSION=%2"
      SHIFT
    )
  )

  REM Enable testing (enable test type (all, integration, or unit)
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_TESTS!" (
    SET ARGUMENT_IS_TEST=!TRUE!
    SET ENABLE_TESTS=!TRUE!
  )
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_INTEGRATION_TESTS!" (
    SET ARGUMENT_IS_TEST=!TRUE!
    SET ENABLE_INTEGRATION_TESTS=!TRUE!
  )
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_UNIT_TESTS!" (
    SET ARGUMENT_IS_TEST=!TRUE!
    SET ENABLE_UNIT_TESTS=!TRUE!
  )
  IF !ARGUMENT_IS_TEST! EQU == !TRUE! (
    REM Ensure testing type hasn't been previously established
    IF !IS_TESTING_ENABLED! EQU !FALSE! (
      REM Indicate testing is enabled
      SET IS_TESTING_ENABLED=!TRUE!

      REM Make sure the Boost root directory exists
      IF [%2] == [] (
        ECHO Invalid Boost Root Directory: Location of Boost must be supplied
        EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
      ) ELSE (
        REM Get the Boost root directory and remove trailing slash (if exists)
        SET "BOOST_ROOT_DIRECTORY=%2"
        IF "!BOOST_ROOT_DIRECTORY:~-1!" == "\" SET "BOOST_ROOT_DIRECTORY=!BOOST_ROOT_DIRECTORY:~0,-1!"
        IF NOT EXIST "!BOOST_ROOT_DIRECTORY!" (
          ECHO Invalid Boost Root Directory: Location does not exist [%2]
          EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
        )
        SHIFT
      )

      REM Reset the argument flag
      SET ARGUMENT_IS_TEST=!FALSE!
    ) ELSE (
      REM Determine which tests were previously parsed
      ECHO Testing Already Indicated: Indicate one type [all, integration, or unit]
    )
  )

  REM Enable libssh2 (clone and build)
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_LIBSSH2!" (
    SET ENABLE_LIBSSH2=!TRUE!
  )

  REM Enable zlib (clone and build)
  IF "!ARGUMENT!" == "!ARGUMENT_ENABLE_ZLIB!" (
    SET ENABLE_ZLIB=!TRUE!
  )

  REM Enable dependency only build(s)
  IF "!ARGUMENT!" == "!ARGUMENT_BUILD_DEPENDENCIES_ONLY!" (
    SET BUILD_DEPENDENCIES_ONLY=!TRUE!
  )

  REM Disable clean build
  IF "!ARGUMENT!" == "!ARGUMENT_DISABLE_CLEAN_BUILD!" (
    SET ENABLE_CLEAN_BUILD=!FALSE!
  )

  REM Disable OpenSSL (clone and build)
  IF "!ARGUMENT!" == "!ARGUMENT_DISABLE_OPENSSL!" (
    SET ENABLE_OPENSSL=!FALSE!
  )

  REM Generate Visual Studio solution (no build)
  IF "!ARGUMENT!" == "!ARGUMENT_GENERATE_SOLUTION!" (
    SET GENERATE_SOLUTION=!TRUE!
  )

  REM Update installation directory for the driver
  IF "!ARGUMENT!" == "!ARGUMENT_INSTALLATION_DIRECTORY!" (
    REM Make sure the installation directory is available
    IF [%2] == [] (
      ECHO Invalid Installation Directory: Directory must be supplied
      EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
    ) ELSE (
      REM Get the driver installation directory
      SET "DRIVER_INSTALLATION_DIRECTORY=%2"
      SHIFT
    )
  )

  REM OpenSSL version (1.0 and 1.1)
  IF "!ARGUMENT!" == "!ARGUMENT_OPENSSL_VERSION!" (
    REM Make sure the version information exists
    IF [%2] == [] (
      ECHO Invalid Version: Version must be supplied when choosing OpenSSL version
      EXIT /B !EXIT_CODE_INVALID_VERSION!
    ) ELSE (
      REM Ensure the OpenSSL version is valid
      IF NOT "%2" == "1.0" (
         IF NOT "%2" == "1.1" (
          ECHO Invalid Version: Version not within range [1.0, 1.1]
          EXIT /B !EXIT_CODE_INVALID_VERSION!
        )
      )

      REM Get the version information and format for branch/tag variable use
      IF "%2" == "1.0" (
        SET OPENSSL_VERSION=1_0
      )
      IF "%2" == "1.1" (
        SET OPENSSL_VERSION=1_1
      )
      SHIFT
    )
  )

  REM Enable the use of Boost atomic library (header only)
  IF "!ARGUMENT!" == "!ARGUMENT_USE_BOOST_ATOMIC!" (
    SET USE_BOOST_ATOMIC=!TRUE!
  )

  REM Help message
  IF "!ARGUMENT!" == "!ARGUMENT_HELP!" (
    CALL :DISPLAYHELP 0
    EXIT /B
  )

  REM Continue to loop through the command line arguments
  GOTO :ARGUMENT_LOOP
)

REM Ensure OpenSSL is enabled if libssh2 or integration tests are enabled
IF !ENABLE_OPENSSL! EQU !FALSE! (
  IF !ENABLE_LIBSSH2! EQU !TRUE! (
    SET ENABLE_OPENSSL=!TRUE!
    ECHO OpenSSL is Required for libssh2: Enabling OpenSSL
  )
)
IF !ENABLE_OPENSSL! EQU !FALSE! (
  IF !ENABLE_TESTS! EQU !TRUE! SET ENABLE_OPENSSL=!TRUE!
  IF !ENABLE_INTEGRATION_TESTS! EQU !TRUE! SET ENABLE_OPENSSL=!TRUE!
  IF !ENABLE_OPENSSL! EQU !TRUE! (
    ECHO OpenSSL is Required for Integration Tests: Enabling OpenSSL
  )
)

REM Ensure static builds are enabled and packages are disabled (if tests)
IF !IS_TESTING_ENABLED! EQU !TRUE! (
  REM Force static for static linking
  IF "!LIBRARY_TYPE!" == "!LIBRARY_TYPE_SHARED!" (
    ECHO Force Static Linking: Testing overrides shared linking
  )
  SET LIBRARY_TYPE=!LIBRARY_TYPE_STATIC!

  REM Determine if package build should be disabled
  IF !ENABLE_BUILD_PACKAGES! EQU !TRUE! (
    ECHO Disabling Package Build: Testing overrides packages
    SET ENABLE_BUILD_PACKAGES=!FALSE!
  )
)

REM Ensure OpenSSL v1.0.x is used for package building
IF !ENABLE_BUILD_PACKAGES! EQU !TRUE! (
  IF "!OPENSSL_VERSION!" == "1_1" (
    REM Force OpenSSL v1.0.x
    ECHO Disabling OpenSSL v1.1.x: Packaging build OpenSSL v1.0.x only
    SET OPENSSL_VERSION=1_0
  )
)
REM Set the OpenSSL branch/tag version to use
FOR %%A IN (!OPENSSL_VERSION!) DO (
  SET "OPENSSL_BRANCH_TAG_VERSION=!OPENSSL_%%A_BRANCH_TAG_VERSION!"
)

REM Determine if zlib should be enabled
IF !ENABLE_ZLIB! EQU !TRUE! (
  SET ENABLE_ZLIB_IS_VALID=!FALSE!
  IF !ENABLE_LIBSSH! EQU !TRUE! SET ENABLE_ZLIB_IS_VALID=!TRUE!
  SET ENABLE_ZLIB=!ENABLE_ZLIB_IS_VALID!
  IF !ENABLE_ZLIB! EQU !FALSE! ECHO Disabling zlib: Not needed for current build configuration
)

REM Create a listing of all the supported Visual Studio versions
SET "LEGACY_VISUAL_STUDIO_INTERNAL_VERSIONS=140 120 110 100"
SET "LEGACY_VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS=14 12 11 10"
SET "LEGACY_VISUAL_STUDIO_VERSIONS=2015 2013 2012 2010"
SET "MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS=141"
SET "MODERN_VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS=15"
SET "MODERN_VISUAL_STUDIO_VERSIONS=2017"
SET "VISUAL_STUDIO_INTERNAL_VERSIONS=!MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS! !LEGACY_VISUAL_STUDIO_INTERNAL_VERSIONS!"
SET "VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS=!MODERN_VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS! !LEGACY_VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS!"
SET "VISUAL_STUDIO_VERSIONS=!MODERN_VISUAL_STUDIO_VERSIONS! !LEGACY_VISUAL_STUDIO_VERSIONS!"

REM Determine Visual Studio version(s) available (modern 2017+)
SET INDEX=0
SET TARGET_COMPILER_VERSION_FOUND=!FALSE!
SET FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS=
FOR %%A IN (!MODERN_VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS!) DO (
  SET /A INDEX+=1
  FOR /F "TOKENS=*" %%B IN ('!VSWHERE! -version %%A -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') DO (
    CALL :GETARRAYELEMENT MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS !INDEX! VISUAL_STUDIO_INTERNAL_VERSION
    SET "AVAILABLE_VISUAL_STUDIO_VERSIONS=!AVAILABLE_VISUAL_STUDIO_VERSIONS! !INDEX!"
    SET "FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS=!FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS! !VISUAL_STUDIO_INTERNAL_VERSION!"

    REM Determine if targeted version can be detected
    IF !VISUAL_STUDIO_INTERNAL_VERSION! EQU !TARGET_COMPILER_VERSION! (
      REM Indicate the compiler was found and set the user choice
      SET TARGET_COMPILER_VERSION_FOUND=!TRUE!
      SET USER_CHOICE_INDEX=!INDEX!
    )
  )
)
IF NOT [!FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS!] == [] SET "FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS=!FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS:~1!"

REM Determine Visual Studio version(s) available (legacy)
FOR %%A IN (!VISUAL_STUDIO_INTERNAL_VERSIONS!) DO (
  IF DEFINED VS%%ACOMNTOOLS (
    SET "AVAILABLE_VISUAL_STUDIO_VERSIONS=!AVAILABLE_VISUAL_STUDIO_VERSIONS! !INDEX!"

    REM Determine if targeted version can be detected
    IF %%A EQU !TARGET_COMPILER_VERSION! (
      REM Indicate the compiler was found and set the user choice
      SET TARGET_COMPILER_VERSION_FOUND=!TRUE!
      SET USER_CHOICE_INDEX=!INDEX!
    )
  )
  SET /A INDEX+=1
)
IF NOT [!AVAILABLE_VISUAL_STUDIO_VERSIONS!] == [] SET "AVAILABLE_VISUAL_STUDIO_VERSIONS=!AVAILABLE_VISUAL_STUDIO_VERSIONS:~1!"

REM Find all available versions of legacy Visual Studio
FOR /F "TOKENS=1,2 DELIMS==" %%A IN ('SET VS') DO (
  IF NOT "%%A" == "VSWHERE" (
    SET EXTRACT_VISUAL_STUDIO_INTERNAL_VERSION=%%A
    SET EXTRACT_VISUAL_STUDIO_INTERNAL_VERSION=!EXTRACT_VISUAL_STUDIO_INTERNAL_VERSION:VS=!
    SET EXTRACT_VISUAL_STUDIO_INTERNAL_VERSION=!EXTRACT_VISUAL_STUDIO_INTERNAL_VERSION:COMNTOOLS=!
    SET "FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS=!FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS! !EXTRACT_VISUAL_STUDIO_INTERNAL_VERSION!"
  )
)
IF [!FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS!] == [] (
  SET "FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS=!FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS!"
) ELSE (
  SET "FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS=!FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS:~1! !FOUND_MODERN_VISUAL_STUDIO_INTERNAL_VERSIONS!"
)

REM Remove versions of Visual Studio that are not applicable for C/C++ driver
FOR %%A IN (!FOUND_VISUAL_STUDIO_INTERNAL_VERSIONS!) DO (
  REM Ensure the other versions of VSXXXCOMNTOOLS are undefined (unset)
  SET KEEP_VISUAL_STUDIO_VERSION=!FALSE!
  FOR %%B IN (!VISUAL_STUDIO_INTERNAL_VERSIONS!) DO (
    IF %%A EQU %%B SET KEEP_VISUAL_STUDIO_VERSION=!TRUE!
  )
  IF !KEEP_VISUAL_STUDIO_VERSION! EQU !FALSE! SET VS%%ACOMNTOOLS=
)

REM Determine if targeted compiler was detected
IF NOT "!TARGET_COMPILER_VERSION!" == "" (
  IF !TARGET_COMPILER_VERSION_FOUND! EQU !FALSE! (
    ECHO Could Not Detect Compiler: !TARGET_COMPILER_VERSION! is not installed
  ) ELSE (
    REM Assign the user choice automatically
    CALL :GETARRAYELEMENTINDEX AVAILABLE_VISUAL_STUDIO_VERSIONS USER_CHOICE_INDEX USER_CHOICE_ENTRY
  )
)

REM Determine the number of Visual Studio version(s)
set NUMBER_OF_VERSIONS=0
FOR %%A IN (!AVAILABLE_VISUAL_STUDIO_VERSIONS!) DO (
  SET /A NUMBER_OF_VERSIONS+=1
)

REM Determine if build can proceed
IF !NUMBER_OF_VERSIONS! EQU 0 (
  ECHO Visual Studio Not Found: Install Visual Studio 2010 - 2017 to complete build
  ECHO	!DOWNLOAD_URL_VISUAL_STUDIO!
  CHOICE /N /T 15 /D N /M "Would you like to download Visual Studio 2017 Community now?"
  IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_VISUAL_STUDIO!
  EXIT /B !EXIT_CODE_MISSING_VISUAL_STUDIO!
)

REM Ensure additional build dependencies are installed
CALL :GETFULLPATH "!CMAKE!" CMAKE_FOUND
IF NOT DEFINED CMAKE_FOUND (
  ECHO CMake Not Found in PATH: CMake v!MINIMUM_VERSION_REQUIRED_CMAKE! is required to complete build
  ECHO	!DOWNLOAD_URL_CMAKE!
  CHOICE /N /T 15 /D N /M "Would you like to download CMake now?"
  IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_CMAKE!
  EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
) ELSE (
  FOR /F "TOKENS=1,2,3* DELIMS= " %%A IN ('!CMAKE! --version') DO IF NOT DEFINED CMAKE_VERSION SET CMAKE_VERSION=%%C
  CALL :COMPAREVERSION !CMAKE_VERSION! !MINIMUM_VERSION_REQUIRED_CMAKE!
  IF !ERRORLEVEL! EQU -1 (
    ECHO Invalid CMake Version Found: CMake v!MINIMUM_VERSION_REQUIRED_CMAKE! is required to complete build
    ECHO	!DOWNLOAD_URL_CMAKE!
    CHOICE /N /T 15 /D N /M "Would you like to download CMake now?"
    IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_CMAKE!
    EXIT /B !EXIT_CODE_INVALID_BUILD_DEPENDENCY_VERSION!
  )
)
CALL :GETFULLPATH "!GIT!" GIT_FOUND
IF NOT DEFINED GIT_FOUND (
  ECHO Git Not Found in PATH: Git is required to complete build
  ECHO	!DOWNLOAD_URL_GIT!
  CHOICE /N /T 15 /D N /M "Would you like to download Git now?"
  IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_GIT!
  EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
)
CALL :GETFULLPATH "!PERL!" PERL_FOUND
IF NOT DEFINED PERL_FOUND (
  REM Perl is only required for building/configuring OpenSSL
  IF !ENABLE_OPENSSL! EQU !TRUE! (
    ECHO Perl Not Found in PATH: Perl is required to complete build
    ECHO	!DOWNLOAD_URL_PERL!
    CHOICE /N /T 15 /D N /M "Would you like to download Perl now?"
    IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_PERL!
    EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
  )
)
CALL :GETFULLPATH "!PYTHON!" PYTHON_FOUND
IF NOT DEFINED PYTHON_FOUND (
  ECHO Python Not Found in PATH: Python v!MINIMUM_VERSION_REQUIRED_PYTHON! is required to complete build
  ECHO	!DOWNLOAD_URL_PYTHON!
  CHOICE /N /T 15 /D N /M "Would you like to download Python now?"
  IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_PYTHON!
  EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
) ELSE (
  FOR /F "TOKENS=1,2* DELIMS= " %%A IN ('!PYTHON! --version 2^>^&1') DO IF NOT DEFINED PYTHON_VERSION SET PYTHON_VERSION=%%B
  CALL :COMPAREVERSION !PYTHON_VERSION! !MINIMUM_VERSION_REQUIRED_PYTHON!
  IF !ERRORLEVEL! EQU -1 (
    ECHO Invalid Python Version Found: Python v!MINIMUM_VERSION_REQUIRED_PYTHON! is required to complete build
    ECHO	!DOWNLOAD_URL_PYTHON!
    CHOICE /N /T 15 /D N /M "Would you like to download Python now?"
    IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_PYTHON!
    EXIT /B !EXIT_CODE_INVALID_BUILD_DEPENDENCY_VERSION!
  )
  REM Python v3.x does not work properly with GYP (libuv build dependency)
  CALL :COMPAREVERSION !PYTHON_VERSION! 3.0.0
  IF !ERRORLEVEL! GEQ 0 (
    ECHO Invalid Python Version Found: Python v3.x is not supported
    ECHO	!DOWNLOAD_URL_PYTHON!
    CHOICE /N /T 15 /D N /M "Would you like to download Python now?"
    IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_PYTHON!
    EXIT /B !EXIT_CODE_INVALID_BUILD_DEPENDENCY_VERSION!
  )
)

REM Determine if we should allow the user to choose compiler version
IF "!ENABLE_BUILD_PACKAGES!" == "!FALSE!" (
  IF !NUMBER_OF_VERSIONS! GTR 1 (
    REM Display discovered Visual Studio versions for selection
    SET INDEX=0
    SET SELECTION_OPTIONS=
    FOR %%A IN (!AVAILABLE_VISUAL_STUDIO_VERSIONS!) DO (
      SET /A INDEX+=1
      SET "SELECTION_OPTIONS=!SELECTION_OPTIONS!!INDEX!"
      CALL :GETARRAYELEMENT VISUAL_STUDIO_VERSIONS %%A VISUAL_STUDIO_VERSION
      ECHO !INDEX!^) Visual Studio !VISUAL_STUDIO_VERSION!
    )

    REM Add the exit option
    ECHO E^) Exit
    SET "SELECTION_OPTIONS=!SELECTION_OPTIONS!E"

    REM Determine if the targeted compiler should be used
    IF !TARGET_COMPILER_VERSION_FOUND! EQU !TRUE! (
      REM Make selection choice for the user
      ECHO Please Select a Compiler: !USER_CHOICE_ENTRY!
    ) ELSE (
      REM Present selection to the user
      CHOICE /C !SELECTION_OPTIONS! /N /T 60 /D E /M "Please Select a Compiler:"
      IF !ERRORLEVEL! GTR !NUMBER_OF_VERSIONS! (
        EXIT /B
      )
      SET USER_CHOICE_ENTRY=!ERRORLEVEL!
    )
    ECHO.

    REM Determine the selection
    CALL :GETARRAYELEMENT AVAILABLE_VISUAL_STUDIO_VERSIONS !USER_CHOICE_ENTRY! USER_SELECTION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_INTERNAL_VERSIONS !USER_SELECTION! VISUAL_STUDIO_INTERNAL_VERSION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS !USER_SELECTION! VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_VERSIONS !USER_SELECTION! VISUAL_STUDIO_VERSION

    REM Ensure the other versions of VSXXXCOMNTOOLS are undefined (unset)
    FOR %%A IN (!VISUAL_STUDIO_INTERNAL_VERSIONS!) DO (
      IF NOT %%A EQU !VISUAL_STUDIO_INTERNAL_VERSION! SET VS%%ACOMNTOOLS=
    )

    REM Ensure the Windows SDK version is undefined (unset)
    IF DEFINED WindowsSDKDir SET WindowsSDKDir=
  ) ELSE (
    CALL :GETARRAYELEMENT VISUAL_STUDIO_INTERNAL_VERSIONS !AVAILABLE_VISUAL_STUDIO_VERSIONS! VISUAL_STUDIO_INTERNAL_VERSION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS !AVAILABLE_VISUAL_STUDIO_VERSIONS! VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_VERSIONS !AVAILABLE_VISUAL_STUDIO_VERSIONS! VISUAL_STUDIO_VERSION
  )

  REM Setup the Visual Studio environment for compiling
  CALL :CONFIGUREVISUALSTUDIOENVIRONMENT !VISUAL_STUDIO_INTERNAL_VERSION! !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! !TARGET_ARCHITECTURE!
  CALL :GETFULLPATH "!DEVENV!" DEVENV_FOUND
  CALL :GETFULLPATH "!MSBUILD!" MSBUILD_FOUND
  CALL :GETFULLPATH "!NMAKE!" NMAKE_FOUND

  REM Determine if Boost Atomic is required
  IF !BUILD_DEPENDENCIES_ONLY! EQU !TRUE! SET USE_BOOST_ATOMIC=!FALSE!

  REM Display summary of build options
  ECHO Build Type:                !BUILD_TYPE!
  ECHO Clean Build:               !ENABLE_CLEAN_BUILD!
  ECHO Dependencies Only:         !BUILD_DEPENDENCIES_ONLY!
  ECHO Examples Enabled:          !ENABLE_EXAMPLES!
  ECHO Library Type:              !LIBRARY_TYPE!
  ECHO OpenSSL Enabled:           !ENABLE_OPENSSL!
  IF !ENABLE_OPENSSL! EQU !TRUE! ECHO   OpenSSL Version:         !OPENSSL_VERSION!
  ECHO Tests Enabled:             !ENABLE_TESTS!
  ECHO Integration Tests Enabled: !ENABLE_INTEGRATION_TESTS!
  ECHO Unit Tests Enabled:        !ENABLE_UNIT_TESTS!
  ECHO libssh2 Enabled:           !ENABLE_LIBSSH2!
  ECHO zlib Enabled:              !ENABLE_ZLIB!
  ECHO Generate Solution          !GENERATE_SOLUTION!
  ECHO Target Architecture:       !TARGET_ARCHITECTURE!
  ECHO Use Boost Atomic:          !USE_BOOST_ATOMIC!
  ECHO Visual Studio:             !VISUAL_STUDIO_VERSION!
  ECHO.
) ELSE (
  REM Ensure package properties are set (ignore commandline arguments)
  SET BUILD_TYPE=!BUILD_TYPE_RELEASE!
  SET ENABLE_CLEAN_BUILD=!TRUE!
  SET ENABLE_EXAMPLES=!FALSE!
  SET ENABLE_OPENSSL=!TRUE!
  SET ENABLE_TESTS=!FALSE!
  SET ENABLE_INTEGRATION_TESTS=!FALSE!
  SET ENABLE_UNIT_TESTS=!FALSE!
  SET ENABLE_ZLIB=!FALSE!
  SET GENERATE_SOLUTION=!FALSE!
  IF !BUILD_DEPENDENCIES_ONLY! EQU !FALSE! (
    SET USE_BOOST_ATOMIC=!TRUE!
    SET ENABLE_LIBSSH2=!FALSE!
  )

  REM Add common 7-zip locations to system path
  SET "PATH=!PATH!;!PROGRAMFILES!\7-zip;!PROGRAMFILES(X86)!\7-zip"

  REM Check for 7-zip to perform package installation
  CALL :GETFULLPATH "!ZIP!" ZIP_FOUND
  IF NOT DEFINED ZIP_FOUND (
    ECHO 7-zip Not Found in PATH: 7-zip is required to build packages
    ECHO	!DOWNLOAD_URL_ZIP!
    CHOICE /N /T 15 /D N /M "Would you like to download 7-zip now?"
    IF !ERRORLEVEL! EQU !YES! START !DOWNLOAD_URL_ZIP!
    EXIT /B !EXIT_CODE_MISSING_BUILD_DEPENDENCY!
  )
)

REM Determine if the build should be cleaned
IF !ENABLE_CLEAN_BUILD! EQU !TRUE! (
  CALL :CLEANDIRECTORY "!ABSOLUTE_BUILD_DIRECTORY!" "Cleaning build directory"
  ECHO.
)

REM Prepare the build directories
IF NOT EXIST "!ABSOLUTE_BUILD_DIRECTORY!" MKDIR "!ABSOLUTE_BUILD_DIRECTORY!"
IF NOT EXIST "!ABSOLUTE_DEPENDENCIES_DIRECTORY!" MKDIR "!ABSOLUTE_DEPENDENCIES_DIRECTORY!"
IF NOT EXIST "!ABSOLUTE_LOG_DIRECTORY!" MKDIR "!ABSOLUTE_LOG_DIRECTORY!"

REM Move to the dependencies directory
PUSHD "!ABSOLUTE_DEPENDENCIES_DIRECTORY!" > NUL

ECHO Cloning Library Dependencies

REM Determine if Boost atomic dependency is required
IF !USE_BOOST_ATOMIC! EQU !TRUE! (
  REM Determine if Boost atomic should be cloned
  IF !IS_TESTING_ENABLED! EQU !FALSE! (
    REM Clone Boost atomic and checkout the appropriate tag
    ECHO Gathering Boost atomic ^(and dependencies^) !BOOST_BRANCH_TAG_VERSION! > "!LOG_BOOST_CLONE!"
    ECHO | SET /P="Gathering Boost atomic ^(and dependencies^) !BOOST_BRANCH_TAG_VERSION! ... "
    SET "BOOST_ATOMIC_DEPENDENCIES=atomic assert config mpl preprocessor static_assert type_traits"
    IF NOT EXIST "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!\include" MKDIR "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!\include"
    REM Store current Visual Studio tools environment variables
    FOR %%A IN (!BOOST_ATOMIC_DEPENDENCIES!) DO (
      !GIT! clone --depth 1 --branch !BOOST_BRANCH_TAG_VERSION! --single-branch !BOOST_REPOSITORY_URL!/%%A "!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!\%%A" >> "!LOG_BOOST_CLONE!" 2>&1
      IF !ERRORLEVEL! EQU 0 (
        XCOPY /E /Y "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!\%%A\include" "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!\include" >> "!LOG_BOOST_CLONE!" 2>&1
        IF NOT !ERRORLEVEL! EQU 0 (
          ECHO FAILED!
          ECHO 	See !LOG_BOOST_CLONE! for more details
          EXIT /B !EXIT_CODE_CHECKOUT_FAILED!
        )
      ) ELSE (
        ECHO FAILED!
        ECHO 	See !LOG_BOOST_CLONE! for more details
        EXIT /B !EXIT_CODE_CLONE_FAILED!
      )
    )
    ECHO done.
  )
)

REM Clone libuv and checkout the appropriate tag
IF NOT EXIST "!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBUV_DIRECTORY!" (
  ECHO Cloning libuv !LIBUV_BRANCH_TAG_VERSION! > "!LOG_LIBUV_BUILD!"
  ECHO | SET /P="Cloning libuv !LIBUV_BRANCH_TAG_VERSION! ... "
  !GIT! clone --depth 1 --branch !LIBUV_BRANCH_TAG_VERSION! --single-branch !LIBUV_REPOSITORY_URL! "!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBUV_DIRECTORY!" >> "!LOG_LIBUV_BUILD!" 2>&1
  IF !ERRORLEVEL! EQU 0 (
    ECHO done.
    REM Clone GYP (libuv dependency) to correctly use googlesource URL
    ECHO. >> "!LOG_LIBUV_BUILD!"
    ECHO Cloning gyp >> "!LOG_LIBUV_BUILD!"
    ECHO | SET /P="Cloning gyp ... "
    !GIT! clone --depth 1 --single-branch !GYP_REPOSITORY_URL! "!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBUV_DIRECTORY!\build\gyp" >> "!LOG_LIBUV_BUILD!" 2>&1
    IF !ERRORLEVEL! EQU 0 (
      ECHO done.
    ) ELSE (
      ECHO FAILED!
      ECHO 	See !LOG_LIBUV_BUILD! for more details
      EXIT /B !EXIT_CODE_CLONE_FAILED!
    )
  ) ELSE (
    ECHO FAILED!
    ECHO 	See !LOG_LIBUV_BUILD! for more details
    EXIT /B !EXIT_CODE_CLONE_FAILED!
  )
)

REM Clone zlib (libssh2 dependency) and checkout the appropriate tag
IF !ENABLE_ZLIB! EQU !TRUE! (
  IF NOT EXIST "!DEPENDENCIES_SOURCE_DIRECTORY!\!ZLIB_DIRECTORY!" (
    ECHO Cloning zlib !ZLIB_BRANCH_TAG_VERSION! > "!LOG_ZLIB_BUILD!"
    ECHO | SET /P="Cloning zlib !ZLIB_BRANCH_TAG_VERSION! ... "
    !GIT! clone --depth 1 --branch !ZLIB_BRANCH_TAG_VERSION! --single-branch !ZLIB_REPOSITORY_URL! "!DEPENDENCIES_SOURCE_DIRECTORY!\!ZLIB_DIRECTORY!" >> "!LOG_ZLIB_BUILD!" 2>&1
    IF !ERRORLEVEL! EQU 0 (
      ECHO done.
    ) ELSE (
      ECHO FAILED!
      ECHO 	See !LOG_ZLIB_BUILD! for more details
      EXIT /B !EXIT_CODE_CLONE_FAILED!
    )
  )
)

REM Determine if libssh2 should be cloned
IF !ENABLE_LIBSSH2! EQU !TRUE! (
  REM Clone libssh2
  IF NOT EXIST "!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBSSH2_DIRECTORY!" (
    ECHO Cloning libssh2 !LIBSSH2_BRANCH_TAG_VERSION! > "!LOG_LIBSSH2_BUILD!"
    ECHO | SET /P="Cloning libssh2 !LIBSSH2_BRANCH_TAG_VERSION! ... "
    !GIT! clone --depth 1 --branch !LIBSSH2_BRANCH_TAG_VERSION! --single-branch !LIBSSH2_REPOSITORY_URL! "!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBSSH2_DIRECTORY!" >> "!LOG_LIBSSH2_BUILD!" 2>&1
    IF !ERRORLEVEL! EQU 0 (
      ECHO done.
    ) ELSE (
      ECHO FAILED!
      ECHO 	See !LOG_LIBSSH2_BUILD! for more details
      EXIT /B !EXIT_CODE_CLONE_FAILED!
    )
  )
)

REM Determine is OpenSSL should be cloned
IF !ENABLE_OPENSSL! EQU !TRUE! (
  REM Clone OpenSSL and checkout the appropriate tag
  IF NOT EXIST "!DEPENDENCIES_SOURCE_DIRECTORY!\!OPENSSL_DIRECTORY!" (
    ECHO Cloning OpenSSL !OPENSSL_BRANCH_TAG_VERSION! > "!LOG_OPENSSL_BUILD!"
    ECHO | SET /P="Cloning OpenSSL !OPENSSL_BRANCH_TAG_VERSION! ... "
    !GIT! clone --depth 1 --branch !OPENSSL_BRANCH_TAG_VERSION! --single-branch !OPENSSL_REPOSITORY_URL! "!DEPENDENCIES_SOURCE_DIRECTORY!\!OPENSSL_DIRECTORY!" >> "!LOG_OPENSSL_BUILD!" 2>&1
    IF !ERRORLEVEL! EQU 0 (
      ECHO done.
    ) ELSE (
      ECHO FAILED!
      ECHO 	See !LOG_OPENSSL_BUILD! for more details
      EXIT /B !EXIT_CODE_CLONE_FAILED!
    )
  )
)

REM Move back to working directory
POPD

REM Determine if the packages are being built
ECHO.
IF "!ENABLE_BUILD_PACKAGES!" == "!FALSE!" (
  ECHO Building Library Dependencies

  REM Determine if libuv needs to be built
  IF NOT EXIST "!ABSOLUTE_LIBUV_LIBRARY_DIRECTORY!" (
    CALL :BUILDLIBUV "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBUV_DIRECTORY!" "!ABSOLUTE_LIBUV_LIBRARY_DIRECTORY!" !TARGET_ARCHITECTURE! !LIBRARY_TYPE! !VISUAL_STUDIO_VERSION! !FALSE! "!LOG_LIBUV_BUILD!"
    IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
  )

  REM Determine if zlib needs to be built
  IF !ENABLE_ZLIB! EQU !TRUE! (
    IF NOT EXIST "!ABSOLUTE_ZLIB_LIBRARY_DIRECTORY!" (
      CALL :BUILDZLIB "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!ZLIB_DIRECTORY!" "!ABSOLUTE_ZLIB_LIBRARY_DIRECTORY!" "!LOG_ZLIB_BUILD!"
      IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
    )
  ) ELSE (
    REM Indicate zlib is disabled
    SET ABSOLUTE_ZLIB_LIBRARY_DIRECTORY=
  )

  REM Determine is OpenSSL should be built
  IF !ENABLE_OPENSSL! EQU !TRUE! (
    REM Determine if OpenSSL needs to be built
    IF NOT EXIST "!ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY!" (
      CALL :BUILDOPENSSL "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!OPENSSL_DIRECTORY!" "!ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY!" "!ABSOLUTE_ZLIB_LIBRARY_DIRECTORY!" !TARGET_ARCHITECTURE! !LIBRARY_TYPE! !ENABLE_SHARED_OPENSSL! !OPENSSL_VERSION! !FALSE! "!LOG_OPENSSL_BUILD!"
      IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
    )
  ) ELSE (
    REM Indicate OpenSSL is disabled
    SET ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY=
  )

  REM Determine is libssh2 should be built
  IF !ENABLE_LIBSSH2! EQU !TRUE! (
    REM Determine if libssh2 needs to be built
    IF NOT EXIST "!ABSOLUTE_LIBSSH2_LIBRARY_DIRECTORY!" (
      CALL :BUILDLIBSSH2 "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBSSH2_DIRECTORY!" "!ABSOLUTE_LIBSSH2_LIBRARY_DIRECTORY!" "!ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY!" "!ABSOLUTE_ZLIB_LIBRARY_DIRECTORY!" !TARGET_ARCHITECTURE! !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! !FALSE! "!LOG_LIBSSH2_BUILD!"
      IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
    )
  ) ELSE (
    REM Indicate libssh2 is disabled
    SET ABSOLUTE_LIBSSH2_LIBRARY_DIRECTORY=
  )

  REM Determine if driver should be built
  IF !BUILD_DEPENDENCIES_ONLY! EQU !FALSE! (
    ECHO.
    ECHO Building Driver

    REM Determine if the driver needs to be built
    SET DRIVER_INSTALLATION_DIRECTORY_OVERRIDDEN=!TRUE!
    IF "!DRIVER_INSTALLATION_DIRECTORY!" == "" (
      SET "DRIVER_INSTALLATION_DIRECTORY=!ABSOLUTE_DRIVER_LIBRARY_DIRECTORY!"
      SET DRIVER_INSTALLATION_DIRECTORY_OVERRIDDEN=!FALSE!
    )
    IF NOT EXIST "!DRIVER_INSTALLATION_DIRECTORY!" (
      SET BOOST_DEPENDENCY_SOURCE_DIRECTORY=
      IF !USE_BOOST_ATOMIC! EQU !TRUE! SET "BOOST_DEPENDENCY_SOURCE_DIRECTORY=!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!"
      CALL :BUILDDRIVER "!ABSOLUTE_BATCH_DIRECTORY!" "!ABSOLUTE_BUILD_DIRECTORY!\!DRIVER_DRIVER_DIRECTORY!" "!DRIVER_INSTALLATION_DIRECTORY!" "!ABSOLUTE_LIBUV_LIBRARY_DIRECTORY!" "!ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY!" "!ABSOLUTE_ZLIB_LIBRARY_DIRECTORY!" "!BOOST_ROOT_DIRECTORY!" "!ABSOLUTE_LIBSSH2_LIBRARY_DIRECTORY!" !BUILD_TYPE! !TARGET_ARCHITECTURE! !LIBRARY_TYPE! !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! !ENABLE_EXAMPLES! !ENABLE_TESTS! !ENABLE_INTEGRATION_TESTS! !ENABLE_UNIT_TESTS! !GENERATE_SOLUTION! "!BOOST_DEPENDENCY_SOURCE_DIRECTORY!" "!LOG_DRIVER_BUILD!"
      IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
    )

    REM Determine if dependencies should be copied
    IF !DRIVER_INSTALLATION_DIRECTORY_OVERRIDDEN! EQU !TRUE! (
      IF EXIST "!DRIVER_INSTALLATION_DIRECTORY!\..\" (
        ECHO | SET /P="Installing cpp-driver dependencies ... "
        XCOPY /E /Y "!ABSOLUTE_DEPENDENCIES_LIBRARIES_DIRECTORY!" "!DRIVER_INSTALLATION_DIRECTORY!\..\" >> "!LOG_DRIVER_BUILD!" 2>&1
        IF NOT !ERRORLEVEL! EQU 0 (
          ECHO FAILED!
          ECHO 	See !LOG_DRIVER_BUILD! for more details
          EXIT /B !EXIT_CODE_BUILD_DRIVER_FAILED!
        )
        ECHO done.
      )
    )

    REM Display success message with location to built driver library
    IF !DRIVER_GENERATE_SOLUTION! EQU !TRUE! (
      ECHO.
      ECHO Visual Studio !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! solution has been successfully generated
      ECHO 	!ABSOLUTE_BUILD_DIRECTORY!\!DRIVER_DRIVER_DIRECTORY!\cassandra.sln
    ) ELSE (
      REM Determine if runtime libraries should be copied
      SET RUNTIME_LIBRARIES_REQUIRED=!FALSE!
      SET "DRIVER_BUILD_DIRECTORY=!ABSOLUTE_BUILD_DIRECTORY!\!DRIVER_DRIVER_DIRECTORY!"
      SET "DRIVER_RUNTIME_DIRECTORY=!DRIVER_BUILD_DIRECTORY!\!BUILD_TYPE!"
      IF !ENABLE_TESTS! EQU !TRUE! SET RUNTIME_LIBRARIES_REQUIRED=!TRUE!
      IF !ENABLE_INTEGRATION_TESTS! EQU !TRUE! SET RUNTIME_LIBRARIES_REQUIRED=!TRUE!
      IF !ENABLE_UNIT_TESTS! EQU !TRUE! SET RUNTIME_LIBRARIES_REQUIRED=!TRUE!
      IF !RUNTIME_LIBRARIES_REQUIRED! EQU !TRUE! (
        ECHO | SET /P="Copying runtime libraries for tests ... "
        IF !ENABLE_SHARED_OPENSSL! EQU !TRUE! (
          XCOPY /Y /E "!ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY!\!LIBRARY_RUNTIME_DIRECTORY!\*.dll" "!DRIVER_RUNTIME_DIRECTORY!" >> "!LOG_DRIVER_BUILD!" 2>&1
          IF NOT !ERRORLEVEL! EQU 0 (
            ECHO FAILED!
            ECHO 	See !LOG_DRIVER_BUILD! for more details
            EXIT /B !EXIT_CODE_BUILD_DRIVER_FAILED!
          )
        )
        ECHO done.
      )
      IF !ENABLE_EXAMPLES! EQU !TRUE! (
        SET "EXAMPLES_DIRECTORY=!DRIVER_BUILD_DIRECTORY!\examples"
        ECHO | SET /P="Copying runtime libraries for examples ... "
        FOR /D %%A IN ("!EXAMPLES_DIRECTORY!\*") DO (
          SET "EXAMPLE_DIRECTORY=!EXAMPLES_DIRECTORY!\%%~NA\!BUILD_TYPE!"
          IF !ENABLE_SHARED_OPENSSL! EQU !TRUE! (
            XCOPY /Y /E "!ABSOLUTE_OPENSSL_LIBRARY_DIRECTORY!\!LIBRARY_RUNTIME_DIRECTORY!\*.dll" "!EXAMPLE_DIRECTORY!" >> "!LOG_DRIVER_BUILD!" 2>&1
            IF NOT !ERRORLEVEL! EQU 0 (
              ECHO FAILED!
              ECHO 	See !LOG_DRIVER_BUILD! for more details
              EXIT /B !EXIT_CODE_BUILD_DRIVER_FAILED!
            )
          )
        )
        ECHO done.
      )

      REM Indicate the driver has been built
      ECHO.
      ECHO Driver has been successfully built [!TARGET_ARCHITECTURE!-bit !BUILD_TYPE!]
      ECHO 	!DRIVER_INSTALLATION_DIRECTORY!
    )
  ) ELSE (
    REM Display success message with location to built dependencies
    ECHO.
    ECHO Dependencies have been successfully built [!TARGET_ARCHITECTURE!-bit !BUILD_TYPE!]
    ECHO 	!ABSOLUTE_DEPENDENCIES_DIRECTORY!
  )
) ELSE (
  REM Ensure the Windows SDK version is undefined (unset)
  IF DEFINED WindowsSDKDir SET WindowsSDKDir=

  REM Store current Visual Studio tools environment variables
  FOR %%A IN (!VISUAL_STUDIO_INTERNAL_VERSIONS!) DO (
    SET "STORED_VS%%ACOMNTOOLS=!VS%%ACOMNTOOLS!"
  )

  REM Iterate through all available Visual Studio versions
  SET INDEX=0
  SET "STORED_PATH=!PATH!"
  FOR %%A IN (!AVAILABLE_VISUAL_STUDIO_VERSIONS!) DO (
    SET /A INDEX+=1
    CALL :GETARRAYELEMENT VISUAL_STUDIO_VERSIONS %%A VISUAL_STUDIO_VERSION
    CALL :GETARRAYELEMENT AVAILABLE_VISUAL_STUDIO_VERSIONS !INDEX! USER_SELECTION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_INTERNAL_VERSIONS !USER_SELECTION! VISUAL_STUDIO_INTERNAL_VERSION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSIONS !USER_SELECTION! VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION
    CALL :GETARRAYELEMENT VISUAL_STUDIO_VERSIONS !USER_SELECTION! VISUAL_STUDIO_VERSION

    REM Determine if both 32 and 64-bit targets can be built
    SET AVAILABLE_TARGET_ARCHITECTURES=!ARCHITECTURE_32BIT!
    IF !SYSTEM_ARCHITECTURE! EQU !ARCHITECTURE_64BIT! (
      SET "AVAILABLE_TARGET_ARCHITECTURES=!AVAILABLE_TARGET_ARCHITECTURES! !ARCHITECTURE_64BIT!"
    )

    REM Ensure the other versions of VSXXXCOMNTOOLS are undefined (unset)
    FOR %%B IN (!VISUAL_STUDIO_INTERNAL_VERSIONS!) DO (
      SET VS%%BCOMNTOOLS=
      IF %%B EQU !VISUAL_STUDIO_INTERNAL_VERSION! SET "VS%%BCOMNTOOLS=!STORED_VS%%BCOMNTOOLS!"
    )

    REM Iterate through all available target architectures
    FOR %%C IN (!AVAILABLE_TARGET_ARCHITECTURES!) DO (
      REM Setup the Visual Studio environment
      CALL :CONFIGUREVISUALSTUDIOENVIRONMENT !VISUAL_STUDIO_INTERNAL_VERSION! !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! %%C
      CALL :GETFULLPATH "!DEVENV!" DEVENV_FOUND
      CALL :GETFULLPATH "!MSBUILD!" MSBUILD_FOUND
      CALL :GETFULLPATH "!NMAKE!" NMAKE_FOUND

      REM Create the base installation locations
      SET DRIVER_PACKAGE_INSTALLATION_DIRECTORY=win%%C\msvc!VISUAL_STUDIO_INTERNAL_VERSION!
      SET DEPENDENCY_PACKAGE_INSTALLATION_DIRECTORY=!DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!DEPENDENCIES_DIRECTORY!
      SET "ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY=!ABSOLUTE_PACKAGES_DIRECTORY!\!DRIVER_PACKAGE_INSTALLATION_DIRECTORY!"

      REM Iterate through shared and static builds
      FOR %%D IN (!LIBRARY_TYPE_SHARED! !LIBRARY_TYPE_STATIC!) DO (
        REM Display summary of build options
        ECHO Building %%D Visual Studio !VISUAL_STUDIO_VERSION! Win%%C Package

        REM Create the installation locations
        CALL :LOWERCASE %%D LOWERCASE_LIBRARY_TYPE
        SET DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY=!DEPENDENCY_PACKAGE_INSTALLATION_DIRECTORY!\!LIBUV_DIRECTORY!\!LOWERCASE_LIBRARY_TYPE!
        SET DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY=!DEPENDENCY_PACKAGE_INSTALLATION_DIRECTORY!\!OPENSSL_DIRECTORY!\!LOWERCASE_LIBRARY_TYPE!
        SET "ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY=!ABSOLUTE_PACKAGES_DIRECTORY!\!DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!"
        SET "ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY=!ABSOLUTE_PACKAGES_DIRECTORY!\!DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!"

        REM Build the dependencies and driver
        CALL :BUILDLIBUV "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBUV_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!" %%C %%D !VISUAL_STUDIO_VERSION! !TRUE! "!LOG_LIBUV_BUILD!"
        IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
        CALL :BUILDOPENSSL "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!OPENSSL_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!" "" %%C %%D !FALSE! !OPENSSL_VERSION! !TRUE! "!LOG_OPENSSL_BUILD!"
        IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
        IF !BUILD_DEPENDENCIES_ONLY! EQU !FALSE! (
          IF EXIST "!ABSOLUTE_BUILD_DIRECTORY!\!DRIVER_DRIVER_DIRECTORY!" CALL :CLEANDIRECTORY "!ABSOLUTE_BUILD_DIRECTORY!\!DRIVER_DRIVER_DIRECTORY!" "Cleaning driver library directory"
          SET BOOST_DEPENDENCY_SOURCE_DIRECTORY=
          IF !VISUAL_STUDIO_VERSION! EQU 2010 SET "BOOST_DEPENDENCY_SOURCE_DIRECTORY=!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!BOOST_DIRECTORY!"
          CALL :BUILDDRIVER "!ABSOLUTE_BATCH_DIRECTORY!" "!ABSOLUTE_BUILD_DIRECTORY!\!DRIVER_DRIVER_DIRECTORY!" "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!" "" "" "" !BUILD_TYPE_RELEASE! %%C %%D !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! !FALSE! !FALSE! !FALSE! !FALSE! !GENERATE_SOLUTION! "!BOOST_DEPENDENCY_SOURCE_DIRECTORY!" "!LOG_DRIVER_BUILD!"
          IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
        )

        REM Build libssh2 (static) as well for dependency only builds
        IF !ENABLE_LIBSSH2! EQU !TRUE! (
          IF "%%D" == "!LIBRARY_TYPE_STATIC!" (
            SET DEPENDENCY_PACKAGE_LIBSSH2_INSTALLATION_DIRECTORY=!DEPENDENCY_PACKAGE_INSTALLATION_DIRECTORY!\!LIBSSH2_DIRECTORY!
            SET "ABSOLUTE_DEPENDENCY_PACKAGE_LIBSSH2_INSTALLATION_DIRECTORY=!ABSOLUTE_PACKAGES_DIRECTORY!\!DEPENDENCY_PACKAGE_LIBSSH2_INSTALLATION_DIRECTORY!"
            CALL :BUILDLIBSSH2 "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBSSH2_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBSSH2_INSTALLATION_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!" "" %%C !VISUAL_STUDIO_INTERNAL_SHORTHAND_VERSION! !TRUE! "!LOG_LIBSSH2_BUILD!"
            IF !ERRORLEVEL! NEQ 0 EXIT /B !ERRORLEVEL!
          )
        )

        REM Clean-up the dependency packages
        IF NOT EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\..\!LIBRARY_INCLUDE_DIRECTORY!" MOVE /Y "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\..\!LIBRARY_INCLUDE_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" RMDIR /S /Q "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF NOT EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\..\!LIBRARY_INCLUDE_DIRECTORY!" MOVE /Y "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\..\!LIBRARY_INCLUDE_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF NOT EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\openssl.cnf" MOVE /Y "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\openssl.cnf" "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" RMDIR /S /Q "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\openssl.cnf" ERASE /S /Q "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\openssl.cnf" >> "!LOG_PACKAGE_BUILD!" 2>&1

        REM Copy distribution files into packages
        IF NOT EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\..\LICENSE" COPY /Y "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!LIBUV_DIRECTORY!\LICENSE" "!ABSOLUTE_DEPENDENCY_PACKAGE_LIBUV_INSTALLATION_DIRECTORY!\.." >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF NOT EXIST "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\..\LICENSE" COPY /Y "!ABSOLUTE_DEPENDENCIES_DIRECTORY!\!DEPENDENCIES_SOURCE_DIRECTORY!\!OPENSSL_DIRECTORY!\LICENSE" "!ABSOLUTE_DEPENDENCY_PACKAGE_OPENSSL_INSTALLATION_DIRECTORY!\.." >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF !BUILD_DEPENDENCIES_ONLY! EQU !FALSE! (
          IF NOT EXIST "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\CHANGELOG.md" COPY /Y "!ABSOLUTE_BATCH_DIRECTORY!\CHANGELOG.md" "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
          IF NOT EXIST "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\LICENSE.txt" COPY /Y "!ABSOLUTE_BATCH_DIRECTORY!\LICENSE.txt" "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
          IF NOT EXIST "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\README.md" COPY /Y "!ABSOLUTE_BATCH_DIRECTORY!\README.md" "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!" >> "!LOG_PACKAGE_BUILD!" 2>&1
        )

        REM Skip a line on the display
        ECHO.
      )

      REM Build the zip packages for the current target architecture and Visual Studio version
      IF !BUILD_DEPENDENCIES_ONLY! EQU !FALSE! (
        ECHO | SET /P="Building the driver package for Win%%C MSVC!VISUAL_STUDIO_INTERNAL_VERSION! ... "
        ECHO !ZIP! a -tzip !ABSOLUTE_PACKAGES_DIRECTORY!\!BUILD_PACKAGE_PREFIX!-!BUILD_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip -r !ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\ -xr^^!!DEPENDENCIES_DIRECTORY! >> "!LOG_PACKAGE_BUILD!"
        !ZIP! a -tzip "!ABSOLUTE_PACKAGES_DIRECTORY!\!BUILD_PACKAGE_PREFIX!-!BUILD_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip" -r "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\*" -xr^^!!DEPENDENCIES_DIRECTORY! >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF NOT !ERRORLEVEL! EQU 0 (
          ECHO FAILED!
          ECHO 	See !LOG_PACKAGE_BUILD! for more details
          EXIT /B !EXIT_CODE_PACKAGE_FAILED!
        )
        ECHO done.
      )
      ECHO | SET /P="Building the libuv package for Win%%C MSVC!VISUAL_STUDIO_INTERNAL_VERSION! ... "
      ECHO !ZIP! a -tzip "!ABSOLUTE_PACKAGES_DIRECTORY!\libuv-!LIBUV_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip" -r !ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!DEPENDENCIES_DIRECTORY!\!LIBUV_DIRECTORY!\ >> "!LOG_PACKAGE_BUILD!"
      !ZIP! a -tzip "!ABSOLUTE_PACKAGES_DIRECTORY!\libuv-!LIBUV_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip" -r "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!DEPENDENCIES_DIRECTORY!\!LIBUV_DIRECTORY!\*" >> "!LOG_PACKAGE_BUILD!" 2>&1
      IF NOT !ERRORLEVEL! EQU 0 (
        ECHO FAILED!
        ECHO 	See !LOG_PACKAGE_BUILD! for more details
        EXIT /B !EXIT_CODE_PACKAGE_FAILED!
      )
      ECHO done.
      ECHO | SET /P="Building the OpenSSL package for Win%%C MSVC!VISUAL_STUDIO_INTERNAL_VERSION! ... "
      ECHO !ZIP! a -tzip !ABSOLUTE_PACKAGES_DIRECTORY!\openssl-!OPENSSL_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip -r !ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!OPENSSL_DIRECTORY!\ >> "!LOG_PACKAGE_BUILD!"
      !ZIP! a -tzip "!ABSOLUTE_PACKAGES_DIRECTORY!\openssl-!OPENSSL_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip" -r "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!DEPENDENCIES_DIRECTORY!\!OPENSSL_DIRECTORY!\*" >> "!LOG_PACKAGE_BUILD!" 2>&1
      IF NOT !ERRORLEVEL! EQU 0 (
        ECHO FAILED!
        ECHO 	See !LOG_PACKAGE_BUILD! for more details
        EXIT /B !EXIT_CODE_PACKAGE_FAILED!
      )
      ECHO done.
      IF !ENABLE_LIBSSH2! EQU !TRUE! (
        ECHO | SET /P="Building the libssh2 package for Win%%C MSVC!VISUAL_STUDIO_INTERNAL_VERSION! ... "
        ECHO !ZIP! a -tzip "!ABSOLUTE_PACKAGES_DIRECTORY!\libssh2-!LIBSSH2_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip" -r !ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!DEPENDENCIES_DIRECTORY!\!LIBSSH2_DIRECTORY!\ >> "!LOG_PACKAGE_BUILD!"
        !ZIP! a -tzip "!ABSOLUTE_PACKAGES_DIRECTORY!\libssh2-!LIBSSH2_PACKAGE_VERSION!-win%%C-msvc!VISUAL_STUDIO_INTERNAL_VERSION!.zip" -r "!ABSOLUTE_DRIVER_PACKAGE_INSTALLATION_DIRECTORY!\!DEPENDENCIES_DIRECTORY!\!LIBSSH2_DIRECTORY!\*" >> "!LOG_PACKAGE_BUILD!" 2>&1
        IF NOT !ERRORLEVEL! EQU 0 (
          ECHO FAILED!
          ECHO 	See !LOG_PACKAGE_BUILD! for more details
          EXIT /B !EXIT_CODE_PACKAGE_FAILED!
        )
        ECHO done.
      )
      ECHO.

      REM Reset the system PATH
      SET "PATH=!STORED_PATH!"
    )
  )
)

REM Disable delayed expansion
ENDLOCAL

REM Exit the batch operation (Ensures below functions are skipped)
EXIT /B

REM Convert a string to uppercase
REM
REM @param string String to convert to uppercase
REM @param return Uppercase converted string
:UPPERCASE [string] [return]
  SET "UPPERCASE_ALPHABET=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
  SET RETURN=%~1
  FOR %%A IN (!UPPERCASE_ALPHABET!) DO SET RETURN=!RETURN:%%A=%%A!
  SET %2=!RETURN!
  GOTO:EOF

REM Convert a string to lowercase
REM
REM @param string String to convert to lowercase
REM @param return Lowercase converted string
:LOWERCASE [string] [return]
  SET "LOWERCASE_ALPHABET=a b c d e f g h i j k l m n o p q r s t u v w x y z"
  SET RETURN=%~1
  FOR %%A IN (!LOWERCASE_ALPHABET!) DO SET RETURN=!RETURN:%%A=%%A!
  SET %2=!RETURN!
  GOTO:EOF

REM Display the help message and exit with error code
:DISPLAYHELP
  CALL :UPPERCASE !BATCH_FILENAME! BATCH_FILENAME_UPPERCASE
  ECHO Usage: !BATCH_FILENAME_UPPERCASE! [OPTION...]
  ECHO.
  ECHO     !ARGUMENT_BUILD_TYPE_DEBUG!                           Enable debug build
  ECHO     !ARGUMENT_BUILD_TYPE_RELEASE!                         Enable release build ^(default^)
  ECHO     !ARGUMENT_DISABLE_CLEAN_BUILD!                   Disable clean build
  ECHO     !ARGUMENT_BUILD_DEPENDENCIES_ONLY!               Build dependencies only
  ECHO     !ARGUMENT_OPENSSL_VERSION!                 OpenSSL version 1.0, 1.1 ^(default: 1.0^)
  ECHO     !ARGUMENT_TARGET_COMPILER! [version]       141, 140, 120, 110, or 100
  ECHO     !ARGUMENT_DISABLE_OPENSSL!                 Disable OpenSSL support
  ECHO     !ARGUMENT_ENABLE_EXAMPLES!                 Enable example builds
  ECHO     !ARGUMENT_ENABLE_BUILD_PACKAGES! [version]       Enable package generation
  ECHO     !ARGUMENT_ENABLE_ZLIB!                     Enable zlib
  ECHO     !ARGUMENT_GENERATE_SOLUTION!               Generate Visual Studio solution
  ECHO     !ARGUMENT_INSTALLATION_DIRECTORY! [install-dir]       Override installation directory
  ECHO     !ARGUMENT_LIBRARY_TYPE_SHARED!                          Build shared library ^(default^)
  ECHO     !ARGUMENT_LIBRARY_TYPE_STATIC!                          Build static library
  ECHO     !ARGUMENT_ENABLE_SHARED_OPENSSL!           Force shared OpenSSL library
  IF !SYSTEM_ARCHITECTURE! EQU !ARCHITECTURE_32BIT! (
    ECHO     !ARGUMENT_TARGET_ARCHITECTURE_32BIT!                             Target 32-bit build ^(default^)
    ECHO     !ARGUMENT_TARGET_ARCHITECTURE_64BIT!                             Target 64-bit build
  ) ELSE (
    ECHO     !ARGUMENT_TARGET_ARCHITECTURE_32BIT!                             Target 32-bit build
    ECHO     !ARGUMENT_TARGET_ARCHITECTURE_64BIT!                             Target 64-bit build ^(default^)
  )
  ECHO     !ARGUMENT_USE_BOOST_ATOMIC!                Use Boost atomic
  ECHO.
  ECHO     Testing Arguments
  ECHO.
  ECHO     !ARGUMENT_ENABLE_TESTS!
  ECHO          [boost-root-dir]             Enable integration and unit tests build
  ECHO     !ARGUMENT_ENABLE_INTEGRATION_TESTS!
  ECHO          [boost-root-dir]             Enable integration tests build
  ECHO     !ARGUMENT_ENABLE_UNIT_TESTS!
  ECHO          [boost-root-dir]             Enable unit tests build
  ECHO     !ARGUMENT_ENABLE_LIBSSH2!                  Enable libssh2 ^(remote server testing^)
  ECHO.
  ECHO     !ARGUMENT_HELP!                            Display this message
  EXIT /B

REM Get an element from an array
REM
REM @param array Global array to iterate through
REM @param element Element in global array to find
REM @param return Index of element in global array
:GETARRAYELEMENTINDEX [array] [element] [return]
  SET ELEMENT_INDEX=0
  FOR %%A IN (!%~1!) DO (
    SET /A ELEMENT_INDEX+=1
    IF "%%A" == "!%~2!" (
      SET %~3=!ELEMENT_INDEX!
    )
  )
  EXIT /B

REM Get an element from an array
REM
REM @param array Global array to iterate through
REM @param index Index to retrieve
REM @param return Variable to assign retrieved value
:GETARRAYELEMENT [array] [index] [return]
  FOR /F "TOKENS=%~2" %%A IN ("!%~1!") DO SET %~3=%%A
  EXIT /B

REM Get a value from a key=value pair in an environment variable
REM
REM @param pair Key/Value pair to parse
REM @param return Value parsed from key/value pair
:GETVALUE [pair] [return]
  FOR /F "TOKENS=1,2* DELIMS==" %%A IN ('SET %~1') DO SET %~2=%%B
  EXIT /B

REM Get full path for a given executable in the system PATH
REM
REM @param executable Executable to search for in PATH
REM @param return Full path with executable
:GETFULLPATH [executable] [return]
  FOR %%A IN ("%~1") DO SET %~2=%%~$PATH:A
  EXIT /B

REM Compare two version numbers
REM
REM @param version-one Version to compare against another version number
REM @param version-two Version to compare against another version number
REM @return 1 if version-one > version-two
REM         0 if version-one == version-two
REM         -1 if version-one < version-two
:COMPAREVERSION [version-one] [version-two]
  CALL :GETVERSIONINFORMATION %~1 VERSION_ONE_MAJOR VERSION_ONE_MINOR VERSION_ONE_PATCH
  CALL :GETVERSIONINFORMATION %~2 VERSION_TWO_MAJOR VERSION_TWO_MINOR VERSION_TWO_PATCH
  IF !VERSION_ONE_MAJOR! GTR !VERSION_TWO_MAJOR! EXIT /B 1
  IF !VERSION_ONE_MAJOR! LSS !VERSION_TWO_MAJOR! EXIT /B -1
  IF NOT DEFINED VERSION_ONE_MINOR IF NOT DEFINED VERSION_TWO_MINOR EXIT /B 0
  IF !VERSION_ONE_MINOR! GTR !VERSION_TWO_MINOR! EXIT /B 1
  IF !VERSION_ONE_MINOR! LSS !VERSION_TWO_MINOR! EXIT /B -1
  IF NOT DEFINED VERSION_ONE_PATCH IF NOT DEFINED VERSION_TWO_PATCH EXIT /B 0
  IF !VERSION_ONE_PATCH! GTR !VERSION_TWO_PATCH! EXIT /B 1
  IF !VERSION_ONE_PATCH! LSS !VERSION_TWO_PATCH! EXIT /B -1
  EXIT /B 0

REM Get version breakdown [major.minor.patch]
REM
REM @param version String representing the full version
REM @param return-major Major version number parsed from version
REM @param return-minor Minor version number parsed from version
REM @param return-patch Patch version number parsed from version
:GETVERSIONINFORMATION [version] [return-major] [return-minor] [return-patch]
  FOR /F "TOKENS=1,2,3* DELIMS=." %%A IN ("%~1") DO (
    SET %~2=%%A
    SET %~3=%%B
    SET %~4=%%C
  )
  EXIT /B

REM Configure Visual Studio environment
REM
REM @param internal-version Visual Studio internal version (e.b 100, 110, 120,
REM                         140, 141)
REM @param target-architecture 32 or 64-bit
:CONFIGUREVISUALSTUDIOENVIRONMENT [internal-version] [internal-shorthand-version] [target-architecture]
  REM Determine if modern or legacy Visual Studio is being used
  IF %~1 GEQ 141 (
    REM Get the auxiliary build directory (legacy style environment scripts) 
    FOR /F "TOKENS=*" %%A IN ('!VSWHERE! -version %~2 -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') DO SET "VISUAL_STUDIO_COMMON_AUXILIARY_TOOLS_DIRECTORY=%%A\VC\Auxiliary\Build"

    REM Determine the proper environment script to execute
    IF %~3 EQU !ARCHITECTURE_32BIT! (
      SET "VISUAL_STUDIO_ENVIRONMENT_SCRIPT=!VISUAL_STUDIO_COMMON_AUXILIARY_TOOLS_DIRECTORY!\vcvars32.bat"
    ) ELSE (
      SET "VISUAL_STUDIO_ENVIRONMENT_SCRIPT=!VISUAL_STUDIO_COMMON_AUXILIARY_TOOLS_DIRECTORY!\vcvarsx86_amd64.bat"
    )
  ) ELSE (
    REM Get the tools directory
    SET VISUAL_STUDIO_ENVIRONMENT_VARIABLE=VS%~1COMNTOOLS
    CALL :GETVALUE !VISUAL_STUDIO_ENVIRONMENT_VARIABLE! VISUAL_STUDIO_COMMON_AUXILIARY_TOOLS_DIRECTORY

    REM Determine the proper environment script to execute
    IF %~3 EQU !ARCHITECTURE_32BIT! (
      SET "VISUAL_STUDIO_ENVIRONMENT_SCRIPT=!VISUAL_STUDIO_COMMON_AUXILIARY_TOOLS_DIRECTORY!\vsvars32.bat"
    ) ELSE (
      SET "VISUAL_STUDIO_ENVIRONMENT_SCRIPT=!VISUAL_STUDIO_COMMON_AUXILIARY_TOOLS_DIRECTORY!\..\..\VC\bin\x86_amd64\vcvarsx86_amd64.bat"
    )
  )

  REM Execute the environment script for Visual Studio
  IF NOT EXIST "!VISUAL_STUDIO_ENVIRONMENT_SCRIPT!" (
    ECHO Unable to Setup %~3-bit Build Environment: !VISUAL_STUDIO_ENVIRONMENT_SCRIPT! is missing
  )
  CALL "!VISUAL_STUDIO_ENVIRONMENT_SCRIPT!"
  ECHO.
  EXIT /B

REM Clean/Delete a directory
REM
REM @param directory Directory to clean
REM @param message Message to display during clean
:CLEANDIRECTORY [directory] [message]
  IF EXIST "%~1" (
    ECHO | SET /P="%~2 ... "
    RMDIR /S /Q "%~1" > NUL 2>&1
    IF NOT EXIST "%~1" (
      ECHO done.
    ) ELSE (
      ECHO not fully cleaned ... directory is in use.
    )
  )
  EXIT /B

REM Shorten a directory/path
REM
REM @param directory Directory to shorten
REM @parem return-directory Shortened directory
:SHORTENPATH [directory] [return-directory]
  FOR %%A IN ("%~1") DO SET %~2=%%~SA
  EXIT /B

REM Build the libuv library
REM
REM @param source-directory Location of libuv source
REM @param install-directory Location to install libuv library
REM @param target-architecture 32 or 64-bit
REM @param library-type Shared or static
REM @param visual-studio-version Shortened Visual Studio version
REM @param is-clean-after-install True if clean should be performed after
REM                               install; false otherwise
REM @param log-filename Absolute path and filename for log output
:BUILDLIBUV [source-directory] [install-directory] [target-architecture] [library-type] [visual-studio-version] [is-clean-after-install] [log-filename]
  REM Create library variables from arguments
  SET "LIBUV_SOURCE_DIRECTORY=%~1"
  SHIFT
  SET "LIBUV_INSTALL_DIRECTORY=%~1"
  SHIFT
  SET LIBUV_TARGET_ARCHITECTURE=%~1
  SHIFT
  SET "LIBUV_LIBRARY_TYPE=%~1"
  SHIFT
  SET "LIBUV_VISUAL_STUDIO_VERSION=%~1"
  SHIFT
  SET LIBUV_IS_CLEAN_AFTER_INSTALL=%~1
  SHIFT
  SET "LIBUV_LOG_FILENAME=%~1"

  REM Build libuv dependency
  ECHO Building libuv
  PUSHD "!LIBUV_SOURCE_DIRECTORY!" > NUL
  IF !LIBUV_TARGET_ARCHITECTURE! EQU !ARCHITECTURE_32BIT! (
    SET LIBUV_TARGET_ARCHITECTURE=x86
    SET LIBUV_VC_TARGET_ARCHITECTURE=Win32
  ) ELSE (
    SET LIBUV_TARGET_ARCHITECTURE=x64
    SET LIBUV_VC_TARGET_ARCHITECTURE=x64
  )
  IF "!LIBUV_LIBRARY_TYPE!" == "!LIBRARY_TYPE_SHARED!" (
    SET LIBUV_LIBRARY_TYPE=shared
  ) ELSE (
    SET LIBUV_LIBRARY_TYPE=static
  )
  ECHO | SET /P="Configuring libuv ... "
  REM Modify the libuv build script to ensure proper Visual Studio detection
  SET LIBUV_VCBUILD_SCRIPT=vcbuild.bat
  SET LIBUV_VCBUILD_SCRIPT=vcbuild-modified.bat
  TYPE vcbuild.bat | FINDSTR /V /C:"if defined WindowsSDKDir goto select-target" | FINDSTR /V /C:"if defined VCINSTALLDIR goto select-target" > !LIBUV_VCBUILD_SCRIPT!
  REM Handle long PATH issues that can be manifested by calling vcvarsall.bat
  IF DEFINED INCLUDE (
    SET "STORED_INCLUDE=!INCLUDE!"
    SET INCLUDE=
  )
  IF DEFINED LIB (
    SET "STORED_LIB=!LIB!"
    SET LIB=
  )
  IF DEFINED LIBPATH (
    SET "STORED_LIBPATH=!LIBPATH!"
    SET LIBPATH=
  )
  IF DEFINED STORED_PATH (
    SET BEFORE_BATCH_CALL_PATH=!PATH!
    SET PATH=!STORED_PATH!
  )
  ECHO !LIBUV_VCBUILD_SCRIPT! release nobuild vs!LIBUV_VISUAL_STUDIO_VERSION! !LIBUV_TARGET_ARCHITECTURE! !LIBUV_LIBRARY_TYPE! >> "!LIBUV_LOG_FILENAME!"
  CALL !LIBUV_VCBUILD_SCRIPT! release nobuild vs!LIBUV_VISUAL_STUDIO_VERSION! !LIBUV_TARGET_ARCHITECTURE! !LIBUV_LIBRARY_TYPE! >> "!LIBUV_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBUV_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  REM Restore PATH (if necessary)
  IF DEFINED STORED_INCLUDE (
    SET "INCLUDE=!STORED_INCLUDE!"
    SET STORED_INCLUDE=
  )
  IF DEFINED STORED_LIB (
    SET "LIB=!STORED_LIB!"
    SET STORED_LIB=
  )
  IF DEFINED STORED_LIBPATH (
    SET "LIBPATH=!STORED_LIBPATH!"
    SET STORED_LIBPATH=
  )
  IF DEFINED BEFORE_BATCH_CALL_PATH (
    SET "PATH=!BEFORE_BATCH_CALL_PATH!"
    SET BEFORE_BATCH_CALL_PATH=
  )
  ECHO | SET /P="Building libuv ... "
  ECHO !MSBUILD! uv.sln /T:libuv /P:Configuration=Release /P:Platform=!LIBUV_VC_TARGET_ARCHITECTURE! /CLP:NoSummary;NoItemAndPropertyList;Verbosity=minimal /NOLOGO >> "!LIBUV_LOG_FILENAME!"
  !MSBUILD! uv.sln /T:libuv /P:Configuration=Release /P:Platform=!LIBUV_VC_TARGET_ARCHITECTURE! /CLP:NoSummary;NoItemAndPropertyList;Verbosity=minimal /NOLOGO >> "!LIBUV_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBUV_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Installing libuv ... "
  MKDIR "!LIBUV_INSTALL_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!"
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBUV_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  XCOPY /E /Y include "!LIBUV_INSTALL_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!" >> "!LIBUV_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBUV_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  MKDIR "!LIBUV_INSTALL_DIRECTORY!\!LIBRARY_BINARY_DIRECTORY!"
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBUV_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  XCOPY /E /Y Release\lib "!LIBUV_INSTALL_DIRECTORY!\!LIBRARY_BINARY_DIRECTORY!" >> "!LIBUV_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    REM Try again in the other location libuv likes to put files
    XCOPY /Y Release\*.* "!LIBUV_INSTALL_DIRECTORY!\!LIBRARY_BINARY_DIRECTORY!" >> "!LIBUV_LOG_FILENAME!" 2>&1
    IF NOT !ERRORLEVEL! EQU 0 (
      ECHO FAILED!
      ECHO 	See !LIBUV_LOG_FILENAME! for more details
      EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
    )
  )
  ECHO done.
  IF "!LIBUV_IS_CLEAN_AFTER_INSTALL!" == "!TRUE!" (
    ECHO | SET /P="Cleaning libuv build ... "
    ECHO !MSBUILD! uv.sln /T:Clean /P:Configuration=Release /P:Platform=!LIBUV_VC_TARGET_ARCHITECTURE! /CLP:NoSummary;NoItemAndPropertyList;Verbosity=minimal /NOLOGO >> "!LIBUV_LOG_FILENAME!"
    !MSBUILD! uv.sln /T:Clean /P:Configuration=Release /P:Platform=!LIBUV_VC_TARGET_ARCHITECTURE! /CLP:NoSummary;NoItemAndPropertyList;Verbosity=minimal /NOLOGO >> "!LIBUV_LOG_FILENAME!" 2>&1
    IF EXIST Release RMDIR /S /Q Release >> "!LIBUV_LOG_FILENAME!" 2>&1
    ECHO done.
  )
  POPD
  EXIT /B

REM Build OpenSSL library
REM
REM @param source-directory Location of OpenSSL source
REM @param install-directory Location to install OpenSSL library
REM @param zlib-library-directory Library directory for zlib; empty string
REM                               indicates zlib disabled
REM @param target-architecture 32 or 64-bit
REM @param library-type Shared or static
REM @param is-force-shared True if OpenSSL library should be built as a shared
REM                        library; false otherwise
REM                        NOTE: If [library-type] is static and
REM                              [zlib-library-directory] is valid then zlib
REM                              will be statically linked
REM @param openssl-version OpenSSL version being built
REM @param is-clean-after-install True if clean should be performed after
REM                               install; false otherwise
REM @param log-filename Absolute path and filename for log output
:BUILDOPENSSL [source-directory] [install-directory] [zlib-library-directory] [target-architecture] [library-type] [is-force-shared] [openssl-version] [is-clean-after-install] [log-filename]
  REM Create library variables from arguments
  SET "OPENSSL_SOURCE_DIRECTORY=%~1"
  SHIFT
  SET "OPENSSL_INSTALL_DIRECTORY=%~1"
  SHIFT
  SET "DEPENDENCY_ZLIB_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET OPENSSL_TARGET_ARCHITECTURE=%~1
  SHIFT
  SET "OPENSSL_LIBRARY_TYPE=%~1"
  SHIFT
  SET OPENSSL_IS_FORCE_SHARED=%~1
  SHIFT
  SET "OPENSSL_VERSION=%~1"
  SHIFT
  SET OPENSSL_IS_CLEAN_AFTER_INSTALL=%~1
  SHIFT
  SET "OPENSSL_LOG_FILENAME=%~1"

  REM Build OpenSSL dependency
  ECHO Building OpenSSL
  PUSHD "!OPENSSL_SOURCE_DIRECTORY!" > NUL
  ECHO | SET /P="Configuring OpenSSL ... "
  SET "OPENSSL_CONFIGURE_OPTIONS=Configure"
  IF !OPENSSL_TARGET_ARCHITECTURE! EQU !ARCHITECTURE_32BIT! (
    SET "OPENSSL_CONFIGURE_OPTIONS=!OPENSSL_CONFIGURE_OPTIONS! VC-WIN32 no-asm"
  ) ELSE (
    SET "OPENSSL_CONFIGURE_OPTIONS=!OPENSSL_CONFIGURE_OPTIONS! VC-WIN64A no-asm"
  )
  IF NOT "!DEPENDENCY_ZLIB_LIBRARY_DIRECTORY!" == "" (
    REM Determine which zlib library to use (shared or static)
    SET DEPENDENCY_ZLIB_LIBRARY_FILENAME=zlib.lib
    IF "!OPENSSL_LIBRARY_TYPE!" == "!LIBRARY_TYPE_STATIC!" SET DEPENDENCY_ZLIB_LIBRARY_FILENAME=zlibstatic.lib

    REM Add the zlib configuration options
    CALL :SHORTENPATH "!DEPENDENCY_ZLIB_LIBRARY_DIRECTORY!" SHORTENED_DEPENDENCY_ZLIB_LIBRARY_DIRECTORY
    SET "OPENSSL_CONFIGURE_OPTIONS=!OPENSSL_CONFIGURE_OPTIONS! zlib --with-zlib-include=^"!SHORTENED_DEPENDENCY_ZLIB_LIBRARY_DIRECTORY!\!LIBRARY_INCLUDE_DIRECTORY!^" --with-zlib-lib=^"!SHORTENED_DEPENDENCY_ZLIB_LIBRARY_DIRECTORY!\!LIBRARY_BINARY_DIRECTORY!\!DEPENDENCY_ZLIB_LIBRARY_FILENAME!^""
  )
  IF !OPENSSL_IS_FORCE_SHARED! EQU !TRUE! SET OPENSSL_LIBRARY_TYPE=!LIBRARY_TYPE_SHARED!
  IF "!OPENSSL_VERSION!" == "1_1" (
    IF "!OPENSSL_LIBRARY_TYPE!" == "!LIBRARY_TYPE_SHARED!" (
      SET "OPENSSL_CONFIGURE_OPTIONS=!OPENSSL_CONFIGURE_OPTIONS! shared"
    ) ELSE (
      SET "OPENSSL_CONFIGURE_OPTIONS=!OPENSSL_CONFIGURE_OPTIONS! no-shared -static"
    )
  )
  CALL :SHORTENPATH "!OPENSSL_INSTALL_DIRECTORY!" SHORTENED_OPENSSL_INSTALL_DIRECTORY
  !PERL! !OPENSSL_CONFIGURE_OPTIONS! enable-static-engine --openssldir=!SHORTENED_OPENSSL_INSTALL_DIRECTORY! --prefix=!SHORTENED_OPENSSL_INSTALL_DIRECTORY! >> "!OPENSSL_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !OPENSSL_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Building OpenSSL ... "
  IF !OPENSSL_TARGET_ARCHITECTURE! EQU !ARCHITECTURE_32BIT! (
    IF "!OPENSSL_VERSION!" == "1_0" (
      CALL ms\do_ms.bat >> "!OPENSSL_LOG_FILENAME!" 2>&1
    )
  ) ELSE (
    IF "!OPENSSL_VERSION!" == "1_0" (
      CALL ms\do_win64a.bat >> "!OPENSSL_LOG_FILENAME!" 2>&1
    )
  )
  IF "!OPENSSL_VERSION!" == "1_0" (
    IF "!OPENSSL_LIBRARY_TYPE!" == "!LIBRARY_TYPE_SHARED!" (
      SET OPENSSL_MAKEFILE=ms\ntdll.mak
    ) ELSE (
      SET OPENSSL_MAKEFILE=ms\nt.mak
    )
    !NMAKE! /F !OPENSSL_MAKEFILE! >> "!OPENSSL_LOG_FILENAME!" 2>&1
  ) ELSE (
    !NMAKE! >> "!OPENSSL_LOG_FILENAME!" 2>&1
  )
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !OPENSSL_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Installing OpenSSL ..."
  IF "!OPENSSL_VERSION!" == "1_0" (
    !NMAKE! /F !OPENSSL_MAKEFILE! install >> "!OPENSSL_LOG_FILENAME!" 2>&1
  ) ELSE (
    !NMAKE! install >> "!OPENSSL_LOG_FILENAME!" 2>&1
  )
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !OPENSSL_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  IF !OPENSSL_IS_CLEAN_AFTER_INSTALL! EQU !TRUE! (
    ECHO | SET /P="Cleaning OpenSSL build ... "
    !NMAKE! /F !OPENSSL_MAKEFILE! clean >> "!OPENSSL_LOG_FILENAME!" 2>&1
    ECHO done.
  )
  POPD
  EXIT /B

REM Build zlib library
REM
REM @param source-directory Location of zlib source
REM @param install-directory Location to install zlib library
REM @param log-filename Absolute path and filename for log output
:BUILDZLIB [source-directory] [install-directory] [log-filename]
  REM Create library variables from arguments
  SET "ZLIB_SOURCE_DIRECTORY=%~1"
  SHIFT
  SET "ZLIB_INSTALL_DIRECTORY=%~1"
  SHIFT
  SET "ZLIB_LOG_FILENAME=%~1"

  REM Build zlib dependency
  ECHO Building zlib
  PUSHD "!ZLIB_SOURCE_DIRECTORY!" > NUL
  IF NOT EXIST build MKDIR build
  PUSHD build > NUL
  ECHO | SET /P="Configuring zlib ... "
  !CMAKE! !CMAKE_OPTIONS! -G "NMake Makefiles" -DCMAKE_C_FLAGS_RELEASE="/MT /NDEBUG" -DCMAKE_INSTALL_PREFIX="!ZLIB_INSTALL_DIRECTORY!" -DCMAKE_BUILD_TYPE=!BUILD_TYPE_RELEASE! .. >> "!ZLIB_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !ZLIB_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Building zlib ... "
  !CMAKE! !CMAKE_OPTIONS! --build . --config !BUILD_TYPE_RELEASE! >> "!ZLIB_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See!ZLIB_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Installing zlib ... "
  !CMAKE! !CMAKE_OPTIONS! --build . --config !BUILD_TYPE_RELEASE! --target install\fast >> "!ZLIB_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !ZLIB_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  POPD
  POPD
  EXIT /B

REM Build libssh2 library
REM
REM @param source-directory Location of libssh2 source
REM @param install-directory Location to install libssh2 library
REM @param openssl-library-directory Library directory for OpenSSL
REM @param zlib-library-directory Library directory for zlib; empty string
REM                               indicates zlib disabled
REM @param target-architecture 32 or 64-bit
REM @param visual-studio-version Shortened Visual Studio version
REM @param is-clean-after-install True if clean should be performed after
REM                               install; false otherwise
REM @param log-filename Absolute path and filename for log output
:BUILDLIBSSH2 [source-directory] [install-directory] [openssl-library-directory] [zlib-library-directory] [target-architecture] [visual-studio-version] [is-clean-after-install] [log-filename]
  REM Create library variables from arguments
  SET "LIBSSH2_SOURCE_DIRECTORY=%~1"
  SHIFT
  SET "LIBSSH2_INSTALL_DIRECTORY=%~1"
  SHIFT
  SET "DEPENDENCY_OPENSSL_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "DEPENDENCY_ZLIB_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "LIBSSH2_TARGET_ARCHITECTURE=%~1"
  SHIFT
  SET "LIBSSH2_VISUAL_STUDIO_VERSION=%~1"
  SHIFT
  SET LIBSSH2_IS_CLEAN_AFTER_INSTALL=%~1
  SHIFT
  SET "LIBSSH2_LOG_FILENAME=%~1"

  REM Build libssh2 dependency
  IF NOT EXIST "!LIBSSH2_SOURCE_DIRECTORY!\build" MKDIR "!LIBSSH2_SOURCE_DIRECTORY!\build"
  PUSHD "!LIBSSH2_SOURCE_DIRECTORY!\build" > NUL
  ECHO | SET /P="Configuring libssh2 ... "
  SET "LIBSSH2_CMAKE_COMMAND_LINE=-G ^"Visual Studio !LIBSSH2_VISUAL_STUDIO_VERSION!"
  IF !LIBSSH2_TARGET_ARCHITECTURE! EQU !ARCHITECTURE_64BIT! (
    SET "LIBSSH2_CMAKE_COMMAND_LINE=!LIBSSH2_CMAKE_COMMAND_LINE! Win64"
  )
  SET "LIBSSH2_CMAKE_COMMAND_LINE=!LIBSSH2_CMAKE_COMMAND_LINE!^""
  SET "LIBSSH2_CMAKE_COMMAND_LINE=!LIBSSH2_CMAKE_COMMAND_LINE! -DCMAKE_BUILD_TYPE=!BUILD_TYPE_RELEASE! -DCMAKE_INSTALL_PREFIX=^"!LIBSSH2_INSTALL_DIRECTORY!^" -DBUILD_SHARED_LIBS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DOPENSSL_ROOT_DIR=^"!DEPENDENCY_OPENSSL_LIBRARY_DIRECTORY!^""
  IF NOT "!DEPENDENCY_ZLIB_LIBRARY_DIRECTORY!" == "" (
    SET "LIBSSH2_CMAKE_COMMAND_LINE=!LIBSSH2_CMAKE_COMMAND_LINE! -DENABLE_ZLIB_COMPRESSION=ON -DZLIB_ROOT=^"!DEPENDENCY_ZLIB_LIBRARY_DIRECTORY!^""
  )
  ECHO !CMAKE! !LIBSSH2_CMAKE_COMMAND_LINE! "!LIBSSH2_SOURCE_DIRECTORY!" >> "!LIBSSH2_LOG_FILENAME!" 2>&1
  !CMAKE! !CMAKE_OPTIONS! !LIBSSH2_CMAKE_COMMAND_LINE! "!LIBSSH2_SOURCE_DIRECTORY!" >> "!LIBSSH2_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBSSH2_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Building libssh2 ... "
  !CMAKE! !CMAKE_OPTIONS! --build . --config !BUILD_TYPE_RELEASE! >> "!LIBSSH2_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBSSH2_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Installing libssh2 ... "
  !CMAKE! !CMAKE_OPTIONS! --build . --config !BUILD_TYPE_RELEASE! --target install >> "!LIBSSH2_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !LIBSSH2_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DEPENDENCY_FAILED!
  )
  ECHO done.
  IF !LIBSSH2_IS_CLEAN_AFTER_INSTALL! EQU !TRUE! (
    ECHO | SET /P="Cleaning libssh2 build ... "
    DEL /S /Q * >> "!LIBSSH2_LOG_FILENAME!" 2>&1
    ECHO done.
  )
  POPD
  EXIT /B

REM Build the driver library
REM
REM @param source-directory Location of driver source
REM @param build-directory Location of driver build directory
REM @param install-directory Location to install driver library
REM @param libuv-library-directory Library directory for libuv
REM @param openssl-library-directory Library directory for OpenSSL; empty
REM                                  string indicates OpenSSL disabled
REM @param zlib-library-directory Library directory for zlib; empty string
REM                               indicates zlib is not required
REM @param boost-library-directory Library directory for Boost; empty string
REM                                indicates tests are disabled
REM @param libssh2-library-directory Library directory for libssh2; empty
REM                                  string indicates tests are disabled
REM @param build-type Debug or release
REM @param target-architecture 32 or 64-bit
REM @param library-type Shared or static
REM @param visual-studio-version Shortened Visual Studio version
REM @param build-examples True to build examples; false otherwise
REM @param build-test True to build tests; false otherwise
REM @param build-integration-test True to build integration tests; false
REM                               otherwise
REM @param build-unit-test True to build unit tests; false otherwise
REM @param generate-solution True to generate visual studio solution file;
REM                          false to perform build using NMake
REM @param boost-atomic-directory Library directory for atomic; empty string
REM                               indicates Boost atomic is not being used
REM @param log-filename Absolute path and filename for log output
:BUILDDRIVER [source-directory] [build-directory] [install-directory] [libuv-library-directory] [openssl-library-directory] [zlib-library-directory] [boost-library-directory] [libssh2-library-directory] [build-type] [target-architecture] [library-type] [visual-studio-version] [build-examples] [build-tests] [build-integration-tests] [build-unit-tests] [generate-solution] [boost-atomic-directory] [log-filename]
  REM Create driver variables from arguments
  SET "DRIVER_SOURCE_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_BUILD_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_INSTALL_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_LIBUV_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_OPENSSL_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_ZLIB_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "TESTS_BOOST_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "TESTS_LIBSSH2_LIBRARY_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_BUILD_TYPE=%~1"
  SHIFT
  SET "DRIVER_TARGET_ARCHITECTURE=%~1"
  SHIFT
  SET "DRIVER_LIBRARY_TYPE=%~1"
  SHIFT
  SET "DRIVER_VISUAL_STUDIO_VERSION=%~1"
  SHIFT
  SET "DRIVER_BUILD_EXAMPLES=%~1"
  SHIFT
  SET "DRIVER_BUILD_TESTS=%~1"
  SHIFT
  SET "DRIVER_BUILD_INTEGRATION_TESTS=%~1"
  SHIFT
  SET "DRIVER_BUILD_UNIT_TESTS=%~1"
  SHIFT
  SET "DRIVER_GENERATE_SOLUTION=%~1"
  SHIFT
  SET "DRIVER_BOOST_DEPENDENCY_SOURCE_DIRECTORY=%~1"
  SHIFT
  SET "DRIVER_LOG_FILENAME=%~1"

  REM Build the driver
  IF NOT EXIST "!DRIVER_BUILD_DIRECTORY!" MKDIR "!DRIVER_BUILD_DIRECTORY!"
  PUSHD "!DRIVER_BUILD_DIRECTORY!" > NUL
  IF !DRIVER_GENERATE_SOLUTION! EQU !TRUE! (
    ECHO | SET /P="Generating driver solution ... "
  ) ELSE (
    ECHO | SET /P="Configuring driver ... "
  )
  SET "DRIVER_CMAKE_COMMAND_LINE=-G ^"Visual Studio !DRIVER_VISUAL_STUDIO_VERSION!"
  IF !DRIVER_TARGET_ARCHITECTURE! EQU !ARCHITECTURE_64BIT! (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! Win64"
  )
  SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE!^""
  IF !DRIVER_BUILD_EXAMPLES! EQU !TRUE! (
    SET DRIVER_BUILD_EXAMPLES=ON
  ) ELSE (
    SET DRIVER_BUILD_EXAMPLES=OFF
  )
  SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_MULTICORE_COMPILATION=ON -DCMAKE_INSTALL_PREFIX=^"!DRIVER_INSTALL_DIRECTORY!^" -DCMAKE_BUILD_TYPE=!DRIVER_BUILD_TYPE! -DCASS_BUILD_EXAMPLES=!DRIVER_BUILD_EXAMPLES! -DLIBUV_ROOT_DIR=^"!DRIVER_LIBUV_LIBRARY_DIRECTORY!^""
  IF NOT "!DRIVER_OPENSSL_LIBRARY_DIRECTORY!" == "" (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_OPENSSL=ON -DOPENSSL_ROOT_DIR=^"!DRIVER_OPENSSL_LIBRARY_DIRECTORY!^""
  ) ELSE (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_OPENSSL=OFF"
  )
  IF NOT "!DRIVER_ZLIB_LIBRARY_DIRECTORY!" == "" (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_ZLIB=ON -DZLIB_ROOT_DIR=^"!DRIVER_ZLIB_LIBRARY_DIRECTORY!^""
  ) ELSE (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_ZLIB=OFF"
  )
  IF "!DRIVER_LIBRARY_TYPE!" == "!LIBRARY_TYPE_SHARED!" (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_BUILD_STATIC=OFF"
    SET DRIVER_VISUAL_STUDIO_TARGETS=cassandra
  ) ELSE (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_BUILD_STATIC=ON -DCASS_USE_STATIC_LIBS=ON"
    SET DRIVER_VISUAL_STUDIO_TARGETS=cassandra_static
  )
  IF !DRIVER_BUILD_TESTS! EQU !TRUE! SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_BUILD_TESTS=ON"
  IF !DRIVER_BUILD_INTEGRATION_TESTS! EQU !TRUE! SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_BUILD_INTEGRATION_TESTS=ON"
  IF !DRIVER_BUILD_UNIT_TESTS! EQU !TRUE! SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_BUILD_UNIT_TESTS=ON"
  IF NOT "!TESTS_BOOST_LIBRARY_DIRECTORY!" == "" (
    REM Determine if using Boost distributed or include/lib binaries
    SET "BOOST_DISTRIBUTION_ROOT_DIRECTORY=!TESTS_BOOST_LIBRARY_DIRECTORY!"
    SET "BOOST_DISTRIBUTION_INCLUDE_DIRECTORY=!BOOST_DISTRIBUTION_ROOT_DIRECTORY!"
    SET "BOOST_DISTRIBUTION_LIBRARY_DIRECTORY=!BOOST_DISTRIBUTION_ROOT_DIRECTORY!\lib!DRIVER_TARGET_ARCHITECTURE!-msvc-!DRIVER_VISUAL_STUDIO_VERSION!.0"
    IF NOT EXIST "!BOOST_DISTRIBUTION_LIBRARY_DIRECTORY!" (
      SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DBOOST_ROOT_DIR=^"!TESTS_BOOST_LIBRARY_DIRECTORY!^""
    ) ELSE (
      SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DBOOST_ROOT=^"!BOOST_DISTRIBUTION_ROOT_DIRECTORY!^" -DBOOST_INCLUDEDIR=^"!BOOST_DISTRIBUTION_INCLUDE_DIRECTORY!^" -DBOOST_LIBRARYDIR=^"!BOOST_DISTRIBUTION_LIBRARY_DIRECTORY!^""
    )
  )
  IF NOT "!TESTS_LIBSSH2_LIBRARY_DIRECTORY!" == "" (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_LIBSSH2=ON -DLIBSSH2_ROOT_DIR=^"!TESTS_LIBSSH2_LIBRARY_DIRECTORY!^""
  ) ELSE (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_LIBSSH2=OFF"
  )
  IF NOT "!DRIVER_BOOST_DEPENDENCY_SOURCE_DIRECTORY!" == "" (
    SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DCASS_USE_BOOST_ATOMIC=ON"
    IF "!TESTS_BOOST_LIBRARY_DIRECTORY!" == "" (
      SET "DRIVER_CMAKE_COMMAND_LINE=!DRIVER_CMAKE_COMMAND_LINE! -DBOOST_ROOT_DIR=^"!DRIVER_BOOST_DEPENDENCY_SOURCE_DIRECTORY!^""
    )
  )
  ECHO !CMAKE! !DRIVER_CMAKE_COMMAND_LINE! "!DRIVER_SOURCE_DIRECTORY!" >> "!DRIVER_LOG_FILENAME!" 2>&1
  !CMAKE! !CMAKE_OPTIONS! !DRIVER_CMAKE_COMMAND_LINE! "!DRIVER_SOURCE_DIRECTORY!" >> "!DRIVER_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !DRIVER_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DRIVER_FAILED!
  )
  ECHO done.
  IF !DRIVER_GENERATE_SOLUTION! EQU !TRUE! (
    POPD
    EXIT /B
  )
  ECHO | SET /P="Building driver ... "
  !CMAKE! !CMAKE_OPTIONS! --build . --config !DRIVER_BUILD_TYPE! >> "!DRIVER_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !DRIVER_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DRIVER_FAILED!
  )
  ECHO done.
  ECHO | SET /P="Installing driver ... "
  !CMAKE! !CMAKE_OPTIONS! --build . --config !DRIVER_BUILD_TYPE! --target install >> "!DRIVER_LOG_FILENAME!" 2>&1
  IF NOT !ERRORLEVEL! EQU 0 (
    ECHO FAILED!
    ECHO 	See !DRIVER_LOG_FILENAME! for more details
    EXIT /B !EXIT_CODE_BUILD_DRIVER_FAILED!
  )
  ECHO done.
  POPD
  EXIT /B
